[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: flock, FAGAIN, and FWOULDBLOCK



On Sun, Feb 22, 2009 at 05:49:24PM -0500, Kyle McMartin wrote:
> > according to the flock(2) man page, flock should return EWOULDBLOCK 
> > when a file is locked and the LOCK_NB flag was selected. But on hppa, 
> > it seems to return EAGAIN which is not the same. Where is the bug 
> > here? In the kernel, glibc, or manpages-dev?
> > 
> > This causes problems in apr since it only checks for EWOULDBLOCK.
> > 
> 
> Ugh. Fail.
> 
> EWOULDBLOCK is defined to be EAGAIN on every architecture but parisc,
> since HPUX has different errno values for EAGAIN and EWOULDBLOCK.
> 
> Definitely a kernel bug, if posix says it should return EWOULDBLOCK...
> 

This is really going to suck, it looks like a lot of the locking
primitives used EAGAIN and EWOULDBLOCK interchangeably... The fcntl
manpage says 'EAGAIN or EWOULDBLOCK' so is flock(2) the only problem
here? From a quick glance at posix, fcntl(2) returning EAGAIN is
correct.

My guess is, I'll be able to sort this out with a simple

diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 71b3195..18e8542 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -156,6 +156,17 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
 
 /* Fucking broken ABI */
 
+asmlinkage long parisc_flock(unsigned int fd, unsigned int cmd)
+{
+	long ret;
+
+	ret = sys_flock(fd, cmd);
+	if (ret == -EAGAIN)
+		ret = -EWOULDBLOCK;	/* fuck you HPUX */
+
+	return ret;
+}
+
 #ifdef CONFIG_64BIT
 asmlinkage long parisc_truncate64(const char __user * path,
 					unsigned int high, unsigned int low)
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 303d2b6..8c62951 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -226,7 +226,7 @@
 	/* it is POSSIBLE that select will be OK because even though fd_set
 	 * contains longs, the macros and sizes are clever. */
 	ENTRY_COMP(select)
-	ENTRY_SAME(flock)
+	ENTRY_OURS(flock)
 	ENTRY_SAME(msync)
 	/* struct iovec contains pointers */
 	ENTRY_COMP(readv)		/* 145 */

but somehow I suspect this interchangeable use of EAGAIN and EWOULDBLOCK
is going to reveal latent problems in this part of the kernel I would
rather not delve into...

cheers, Kyle


Reply to: