From: Chris Wright <chrisw@osdl.org>

This is a rather ugly fix, but it demonstrates the hole.  It's possible for
a posix lock to get applied after the final close of the file.  This means
locks_remove_posix misses the yet to be created posix lock, and on final
fput when leaving fcntl, locks_remove_flock will BUG().  I was able to
reproduce Ivan's bugreport.  I doubt it's the right/best fix, but it's
functional (no more BUG()).

Signed-off-by: Chris Wright <chrisw@osdl.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/fcntl.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff -puN fs/fcntl.c~posix-locks-bug-fix fs/fcntl.c
--- 25/fs/fcntl.c~posix-locks-bug-fix	2004-10-01 21:08:48.457390480 -0700
+++ 25-akpm/fs/fcntl.c	2004-10-01 21:08:48.472388200 -0700
@@ -363,7 +363,7 @@ static long do_fcntl(int fd, unsigned in
 
 asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {	
-	struct file *filp;
+	struct file *filp, *filp2;
 	long err = -EBADF;
 
 	filp = fget(fd);
@@ -378,6 +378,11 @@ asmlinkage long sys_fcntl(unsigned int f
 
 	err = do_fcntl(fd, cmd, arg, filp);
 
+	filp2 = fget(fd);
+	if (filp2 != filp)
+		locks_remove_posix(filp, current->files);
+	if (filp2)
+		fput(filp2);
  	fput(filp);
 out:
 	return err;
@@ -386,7 +391,7 @@ out:
 #if BITS_PER_LONG == 32
 asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
 {	
-	struct file * filp;
+	struct file *filp, *filp2;
 	long err;
 
 	err = -EBADF;
@@ -413,6 +418,12 @@ asmlinkage long sys_fcntl64(unsigned int
 			err = do_fcntl(fd, cmd, arg, filp);
 			break;
 	}
+
+	filp2 = fget(fd);
+	if (filp2 != filp)
+		locks_remove_posix(filp, current->files);
+	if (filp2)
+		fput(filp2);
 	fput(filp);
 out:
 	return err;
_