Binary files 2.4.0-test6-pre9/ID and 2.4.0-test6-pre9-file_lock-1/ID differ
diff -urN 2.4.0-test6-pre9/arch/i386/kernel/entry.S 2.4.0-test6-pre9-file_lock-1/arch/i386/kernel/entry.S
--- 2.4.0-test6-pre9/arch/i386/kernel/entry.S	Thu Aug 10 04:05:29 2000
+++ 2.4.0-test6-pre9-file_lock-1/arch/i386/kernel/entry.S	Thu Aug 10 04:18:56 2000
@@ -641,6 +641,7 @@
 	.long SYMBOL_NAME(sys_pivot_root)
 	.long SYMBOL_NAME(sys_mincore)
 	.long SYMBOL_NAME(sys_madvise)
+	.long SYMBOL_NAME(sys_fcntl64)		/* 220 */
 
 
 	/*
@@ -649,6 +650,6 @@
 	 * entries. Don't panic if you notice that this hasn't
 	 * been shrunk every time we add a new system call.
 	 */
-	.rept NR_syscalls-219
+	.rept NR_syscalls-220
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -urN 2.4.0-test6-pre9/fs/fcntl.c 2.4.0-test6-pre9-file_lock-1/fs/fcntl.c
--- 2.4.0-test6-pre9/fs/fcntl.c	Thu Aug 10 04:05:30 2000
+++ 2.4.0-test6-pre9-file_lock-1/fs/fcntl.c	Thu Aug 10 04:31:25 2000
@@ -209,16 +209,11 @@
 	return 0;
 }
 
-asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{	
-	struct file * filp;
-	long err = -EBADF;
+static long do_fcntl(unsigned int fd, unsigned int cmd,
+		     unsigned long arg, struct file * filp)
+{
+	long err = 0;
 
-	filp = fget(fd);
-	if (!filp)
-		goto out;
-	err = 0;
-	lock_kernel();
 	switch (cmd) {
 		case F_DUPFD:
 			err = -EINVAL;
@@ -287,11 +282,60 @@
 				err = sock_fcntl (filp, cmd, arg);
 			break;
 	}
+
+	return err;
+}
+
+asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{	
+	struct file * filp;
+	long err = -EBADF;
+
+	filp = fget(fd);
+	if (!filp)
+		goto out;
+
+	lock_kernel();
+	err = do_fcntl(fd, cmd, arg, filp);
+	unlock_kernel();
+
+ 	fput(filp);
+out:
+	return err;
+}
+
+#if BITS_PER_LONG == 32
+asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
+{	
+	struct file * filp;
+	long err;
+
+	err = -EBADF;
+	filp = fget(fd);
+	if (!filp)
+		goto out;
+
+	lock_kernel();
+	switch (cmd) {
+		case F_GETLK64:
+			err = fcntl_getlk64(fd, (struct flock64 *) arg);
+			break;
+		case F_SETLK64:
+			err = fcntl_setlk64(fd, cmd, (struct flock64 *) arg);
+			break;
+		case F_SETLKW64:
+			err = fcntl_setlk64(fd, cmd, (struct flock64 *) arg);
+			break;
+		default:
+			err = do_fcntl(fd, cmd, arg, filp);
+			break;
+	}
 	unlock_kernel();
 	fput(filp);
 out:
 	return err;
 }
+#endif
 
 /* Table to convert sigio signal codes into poll band bitmaps */
 
diff -urN 2.4.0-test6-pre9/fs/locks.c 2.4.0-test6-pre9-file_lock-1/fs/locks.c
--- 2.4.0-test6-pre9/fs/locks.c	Tue Jul 11 03:50:35 2000
+++ 2.4.0-test6-pre9-file_lock-1/fs/locks.c	Thu Aug 10 18:06:44 2000
@@ -205,8 +205,8 @@
 /* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
  * style lock.
  */
-static int posix_make_lock(struct file *filp, struct file_lock *fl,
-			   struct flock *l)
+static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
+			       struct flock *l)
 {
 	loff_t start;
 
@@ -254,6 +254,57 @@
 	return (1);
 }
 
+#if BITS_PER_LONG == 32
+static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
+				 struct flock64 *l)
+{
+	loff_t start;
+
+	switch (l->l_whence) {
+	case 0: /*SEEK_SET*/
+		start = 0;
+		break;
+	case 1: /*SEEK_CUR*/
+		start = filp->f_pos;
+		break;
+	case 2: /*SEEK_END*/
+		start = filp->f_dentry->d_inode->i_size;
+		break;
+	default:
+		return (0);
+	}
+
+	if (((start += l->l_start) < 0) || (l->l_len < 0))
+		return (0);
+	fl->fl_end = start + l->l_len - 1;
+	if (l->l_len > 0 && fl->fl_end < 0)
+		return (0);
+	fl->fl_start = start;	/* we record the absolute position */
+	if (l->l_len == 0)
+		fl->fl_end = OFFSET_MAX;
+	
+	fl->fl_owner = current->files;
+	fl->fl_pid = current->pid;
+	fl->fl_file = filp;
+	fl->fl_flags = FL_POSIX;
+	fl->fl_notify = NULL;
+	fl->fl_insert = NULL;
+	fl->fl_remove = NULL;
+
+	switch (l->l_type) {
+	case F_RDLCK:
+	case F_WRLCK:
+	case F_UNLCK:
+		fl->fl_type = l->l_type;
+		break;
+	default:
+		return (0);
+	}
+
+	return (1);
+}
+#endif
+
 /* Check if two locks overlap each other.
  */
 static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
@@ -893,7 +944,7 @@
 int fcntl_getlk(unsigned int fd, struct flock *l)
 {
 	struct file *filp;
-	struct file_lock *fl, *file_lock = locks_alloc_lock();
+	struct file_lock *fl, file_lock;
 	struct flock flock;
 	int error;
 
@@ -909,27 +960,41 @@
 	if (!filp)
 		goto out;
 
-	if (!posix_make_lock(filp, file_lock, &flock))
+	error = -EINVAL;
+	if (!flock_to_posix_lock(filp, &file_lock, &flock))
 		goto out_putf;
 
 	if (filp->f_op->lock) {
-		error = filp->f_op->lock(filp, F_GETLK, file_lock);
+		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
 		if (error < 0)
 			goto out_putf;
 		else if (error == LOCK_USE_CLNT)
 		  /* Bypass for NFS with no locking - 2.0.36 compat */
-		  fl = posix_test_lock(filp, file_lock);
+		  fl = posix_test_lock(filp, &file_lock);
 		else
-		  fl = (file_lock->fl_type == F_UNLCK ? NULL : file_lock);
+		  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
 	} else {
-		fl = posix_test_lock(filp, file_lock);
+		fl = posix_test_lock(filp, &file_lock);
 	}
  
 	flock.l_type = F_UNLCK;
 	if (fl != NULL) {
 		flock.l_pid = fl->fl_pid;
+#if BITS_PER_LONG == 32
+		/*
+		 * Make sure we can represent the posix lock via
+		 * legacy 32bit flock.
+		 */
+		error = -EOVERFLOW;
+		if (fl->fl_end > OFFT_OFFSET_MAX)
+			goto out_putf;
+#endif
 		flock.l_start = fl->fl_start;
+#if BITS_PER_LONG == 32
+		flock.l_len = fl->fl_end == OFFT_OFFSET_MAX ? 0 :
+#else
 		flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
+#endif
 			fl->fl_end - fl->fl_start + 1;
 		flock.l_whence = 0;
 		flock.l_type = fl->fl_type;
@@ -941,7 +1006,6 @@
 out_putf:
 	fput(filp);
 out:
-	locks_free_lock(file_lock);
 	return error;
 }
 
@@ -951,7 +1015,7 @@
 int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
 {
 	struct file *filp;
-	struct file_lock *file_lock = locks_alloc_lock();
+	struct file_lock file_lock;
 	struct flock flock;
 	struct inode *inode;
 	int error;
@@ -993,7 +1057,7 @@
 	}
 
 	error = -EINVAL;
-	if (!posix_make_lock(filp, file_lock, &flock))
+	if (!flock_to_posix_lock(filp, &file_lock, &flock))
 		goto out_putf;
 	
 	error = -EBADF;
@@ -1031,18 +1095,160 @@
 	}
 
 	if (filp->f_op->lock != NULL) {
-		error = filp->f_op->lock(filp, cmd, file_lock);
+		error = filp->f_op->lock(filp, cmd, &file_lock);
+		if (error < 0)
+			goto out_putf;
+	}
+	error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW);
+
+out_putf:
+	fput(filp);
+out:
+	return error;
+}
+
+#if BITS_PER_LONG == 32
+/* Report the first existing lock that would conflict with l.
+ * This implements the F_GETLK command of fcntl().
+ */
+int fcntl_getlk64(unsigned int fd, struct flock64 *l)
+{
+	struct file *filp;
+	struct file_lock *fl, file_lock;
+	struct flock64 flock;
+	int error;
+
+	error = -EFAULT;
+	if (copy_from_user(&flock, l, sizeof(flock)))
+		goto out;
+	error = -EINVAL;
+	if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
+		goto out;
+
+	error = -EBADF;
+	filp = fget(fd);
+	if (!filp)
+		goto out;
+
+	error = -EINVAL;
+	if (!flock64_to_posix_lock(filp, &file_lock, &flock))
+		goto out_putf;
+
+	if (filp->f_op->lock) {
+		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+		if (error < 0)
+			goto out_putf;
+		else if (error == LOCK_USE_CLNT)
+		  /* Bypass for NFS with no locking - 2.0.36 compat */
+		  fl = posix_test_lock(filp, &file_lock);
+		else
+		  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
+	} else {
+		fl = posix_test_lock(filp, &file_lock);
+	}
+ 
+	flock.l_type = F_UNLCK;
+	if (fl != NULL) {
+		flock.l_pid = fl->fl_pid;
+		flock.l_start = fl->fl_start;
+		flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
+			fl->fl_end - fl->fl_start + 1;
+		flock.l_whence = 0;
+		flock.l_type = fl->fl_type;
+	}
+	error = -EFAULT;
+	if (!copy_to_user(l, &flock, sizeof(flock)))
+		error = 0;
+  
+out_putf:
+	fput(filp);
+out:
+	return error;
+}
+
+/* Apply the lock described by l to an open file descriptor.
+ * This implements both the F_SETLK and F_SETLKW commands of fcntl().
+ */
+int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l)
+{
+	struct file *filp;
+	struct file_lock file_lock;
+	struct flock64 flock;
+	struct inode *inode;
+	int error;
+
+	/*
+	 * This might block, so we do it before checking the inode.
+	 */
+	error = -EFAULT;
+	if (copy_from_user(&flock, l, sizeof(flock)))
+		goto out;
+
+	/* Get arguments and validate them ...
+	 */
+
+	error = -EBADF;
+	filp = fget(fd);
+	if (!filp)
+		goto out;
+
+	error = -EINVAL;
+	inode = filp->f_dentry->d_inode;
+
+	/* Don't allow mandatory locks on files that may be memory mapped
+	 * and shared.
+	 */
+	if (IS_MANDLOCK(inode) &&
+	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
+		struct vm_area_struct *vma;
+		struct address_space *mapping = inode->i_mapping;
+		spin_lock(&mapping->i_shared_lock);
+		for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) {
+			if (!(vma->vm_flags & VM_MAYSHARE))
+				continue;
+			spin_unlock(&mapping->i_shared_lock);
+			error = -EAGAIN;
+			goto out_putf;
+		}
+		spin_unlock(&mapping->i_shared_lock);
+	}
+
+	error = -EINVAL;
+	if (!flock64_to_posix_lock(filp, &file_lock, &flock))
+		goto out_putf;
+	
+	error = -EBADF;
+	switch (flock.l_type) {
+	case F_RDLCK:
+		if (!(filp->f_mode & FMODE_READ))
+			goto out_putf;
+		break;
+	case F_WRLCK:
+		if (!(filp->f_mode & FMODE_WRITE))
+			goto out_putf;
+		break;
+	case F_UNLCK:
+		break;
+	case F_SHLCK:
+	case F_EXLCK:
+	default:
+		error = -EINVAL;
+		goto out_putf;
+	}
+
+	if (filp->f_op->lock != NULL) {
+		error = filp->f_op->lock(filp, cmd, &file_lock);
 		if (error < 0)
 			goto out_putf;
 	}
-	error = posix_lock_file(filp, file_lock, cmd == F_SETLKW);
+	error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW);
 
 out_putf:
 	fput(filp);
 out:
-	locks_free_lock(file_lock);
 	return error;
 }
+#endif /* BITS_PER_LONG == 32 */
 
 /*
  * This function is called when the file is being removed
diff -urN 2.4.0-test6-pre9/fs/stat.c 2.4.0-test6-pre9-file_lock-1/fs/stat.c
--- 2.4.0-test6-pre9/fs/stat.c	Thu Aug 10 04:05:30 2000
+++ 2.4.0-test6-pre9-file_lock-1/fs/stat.c	Thu Aug 10 04:18:56 2000
@@ -52,6 +52,10 @@
 	SET_OLDSTAT_UID(tmp, inode->i_uid);
 	SET_OLDSTAT_GID(tmp, inode->i_gid);
 	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+#if BITS_PER_LONG == 32
+	if (inode->i_size > 0x7fffffff)
+		return -EOVERFLOW;
+#endif	
 	tmp.st_size = inode->i_size;
 	tmp.st_atime = inode->i_atime;
 	tmp.st_mtime = inode->i_mtime;
@@ -74,6 +78,10 @@
 	SET_STAT_UID(tmp, inode->i_uid);
 	SET_STAT_GID(tmp, inode->i_gid);
 	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+#if BITS_PER_LONG == 32
+	if (inode->i_size > 0x7fffffff)
+		return -EOVERFLOW;
+#endif	
 	tmp.st_size = inode->i_size;
 	tmp.st_atime = inode->i_atime;
 	tmp.st_mtime = inode->i_mtime;
diff -urN 2.4.0-test6-pre9/include/asm-alpha/fcntl.h 2.4.0-test6-pre9-file_lock-1/include/asm-alpha/fcntl.h
--- 2.4.0-test6-pre9/include/asm-alpha/fcntl.h	Tue Jul 11 03:50:36 2000
+++ 2.4.0-test6-pre9-file_lock-1/include/asm-alpha/fcntl.h	Thu Aug 10 04:18:56 2000
@@ -63,4 +63,8 @@
 	__kernel_pid_t l_pid;
 };
 
+#ifdef __KERNEL__
+#define flock64	flock
+#endif
+
 #endif
diff -urN 2.4.0-test6-pre9/include/asm-i386/fcntl.h 2.4.0-test6-pre9-file_lock-1/include/asm-i386/fcntl.h
--- 2.4.0-test6-pre9/include/asm-i386/fcntl.h	Tue Jul 11 03:50:37 2000
+++ 2.4.0-test6-pre9-file_lock-1/include/asm-i386/fcntl.h	Thu Aug 10 04:18:56 2000
@@ -35,6 +35,10 @@
 #define F_SETSIG	10	/*  for sockets. */
 #define F_GETSIG	11	/*  for sockets. */
 
+#define F_GETLK64	12	/*  using 'struct flock64' */
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC	1	/* actually anything with low bit set goes */
 
@@ -60,6 +64,14 @@
 	off_t l_start;
 	off_t l_len;
 	pid_t l_pid;
+};
+
+struct flock64 {
+	short  l_type;
+	short  l_whence;
+	loff_t l_start;
+	loff_t l_len;
+	pid_t  l_pid;
 };
 
 #endif
diff -urN 2.4.0-test6-pre9/include/asm-i386/unistd.h 2.4.0-test6-pre9-file_lock-1/include/asm-i386/unistd.h
--- 2.4.0-test6-pre9/include/asm-i386/unistd.h	Wed Mar 15 16:45:13 2000
+++ 2.4.0-test6-pre9-file_lock-1/include/asm-i386/unistd.h	Thu Aug 10 04:18:56 2000
@@ -225,6 +225,7 @@
 #define __NR_mincore		218
 #define __NR_madvise		219
 #define __NR_madvise1		219	/* delete when C lib stub is removed */
+#define __NR_fcntl64		220
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -urN 2.4.0-test6-pre9/include/linux/fs.h 2.4.0-test6-pre9-file_lock-1/include/linux/fs.h
--- 2.4.0-test6-pre9/include/linux/fs.h	Thu Aug 10 04:05:30 2000
+++ 2.4.0-test6-pre9-file_lock-1/include/linux/fs.h	Thu Aug 10 18:37:09 2000
@@ -535,6 +535,7 @@
 #ifndef OFFSET_MAX
 #define INT_LIMIT(x)	(~((x)1 << (sizeof(x)*8 - 1)))
 #define OFFSET_MAX	INT_LIMIT(loff_t)
+#define OFFT_OFFSET_MAX	INT_LIMIT(off_t)
 #endif
 
 extern struct list_head file_lock_list;
@@ -543,6 +544,9 @@
 
 extern int fcntl_getlk(unsigned int, struct flock *);
 extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);
+
+extern int fcntl_getlk64(unsigned int, struct flock64 *);
+extern int fcntl_setlk64(unsigned int, unsigned int, struct flock64 *);
 
 /* fs/locks.c */
 extern void locks_remove_posix(struct file *, fl_owner_t);