Re: flock, FAGAIN, and FWOULDBLOCK

Kyle McMartin
2009-02-23T01:42:25Z

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