[PATCH] 2.5.59: ftruncate/truncate oopses with mandatory locking

From: Faik Uygur (faikuygur@ttnet.net.tr)
Date: Wed Jan 22 2003 - 19:55:30 EST


This patch fixes the truncate/ftruncate oopses with mandatory locking
enabled. The problem with ftruncate is that the local variable fl is
not initialized properly in locks_mandatory_area that it misbehaves at
various places like locks_insert_block. And the problem with truncate
is that the filp variable is NULL at posix_lock_file. The NULL value
comes from do_sys_truncate.

The bug report and details can be found at,
http://bugme.osdl.org/show_bug.cgi?id=280

diff -uNr linux-2.5.59-vanilla/fs/lockd/svclock.c linux-2.5.59/fs/lockd/svclock.c
--- linux-2.5.59-vanilla/fs/lockd/svclock.c Thu Nov 28 00:35:55 2002
+++ linux-2.5.59/fs/lockd/svclock.c Thu Jan 23 00:41:45 2003
@@ -315,7 +315,7 @@
 
 again:
         if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
- error = posix_lock_file(&file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl);
 
                 if (block)
                         nlmsvc_delete_block(block, 0);
@@ -419,7 +419,7 @@
         nlmsvc_cancel_blocked(file, lock);
 
         lock->fl.fl_type = F_UNLCK;
- error = posix_lock_file(&file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl);
 
         return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
 }
@@ -523,7 +523,7 @@
          * following yields an error, this is most probably due to low
          * memory. Retry the lock in a few seconds.
          */
- if ((error = posix_lock_file(&file->f_file, &lock->fl)) < 0) {
+ if ((error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl)) < 0) {
                 printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
                                 -error, __FUNCTION__);
                 nlmsvc_insert_block(block, 10 * HZ);
diff -uNr linux-2.5.59-vanilla/fs/lockd/svcsubs.c linux-2.5.59/fs/lockd/svcsubs.c
--- linux-2.5.59-vanilla/fs/lockd/svcsubs.c Thu Nov 28 00:36:14 2002
+++ linux-2.5.59/fs/lockd/svcsubs.c Thu Jan 23 01:01:51 2003
@@ -176,7 +176,7 @@
                         lock.fl_type = F_UNLCK;
                         lock.fl_start = 0;
                         lock.fl_end = OFFSET_MAX;
- if (posix_lock_file(&file->f_file, &lock) < 0) {
+ if (posix_lock_file(file->f_file.f_dentry->d_inode, &lock) < 0) {
                                 printk("lockd: unlock failure in %s:%d\n",
                                                 __FILE__, __LINE__);
                                 return 1;
diff -uNr linux-2.5.59-vanilla/fs/locks.c linux-2.5.59/fs/locks.c
--- linux-2.5.59-vanilla/fs/locks.c Thu Jan 23 00:02:16 2003
+++ linux-2.5.59/fs/locks.c Thu Jan 23 01:58:16 2003
@@ -678,6 +678,10 @@
         struct file_lock fl;
         int error;
 
+ INIT_LIST_HEAD(&fl.fl_link);
+ INIT_LIST_HEAD(&fl.fl_block);
+ init_waitqueue_head(&fl.fl_wait);
+
         fl.fl_owner = current->files;
         fl.fl_pid = current->tgid;
         fl.fl_file = filp;
@@ -685,9 +689,14 @@
         fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
         fl.fl_start = offset;
         fl.fl_end = offset + count - 1;
+ fl.fl_next = NULL;
+ fl.fl_notify = NULL;
+ fl.fl_insert = NULL;
+ fl.fl_remove = NULL;
+ fl.fl_fasync = NULL;
 
         for (;;) {
- error = posix_lock_file(filp, &fl);
+ error = posix_lock_file(inode, &fl);
                 if (error != -EAGAIN)
                         break;
                 error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
@@ -772,9 +781,8 @@
 
 /**
  * posix_lock_file:
- * @filp: The file to apply the lock to
- * @caller: The lock to be applied
- * @wait: 1 to retry automatically, 0 to return -EAGAIN
+ * @inode: The inode of file to apply the lock to
+ * @request: The lock to be applied
  *
  * Add a POSIX style lock to a file.
  * We merge adjacent locks whenever possible. POSIX locks are sorted by owner
@@ -788,14 +796,13 @@
  * To all purists: Yes, I use a few goto's. Just pass on to the next function.
  */
 
-int posix_lock_file(struct file *filp, struct file_lock *request)
+int posix_lock_file(struct inode *inode, struct file_lock *request)
 {
         struct file_lock *fl;
         struct file_lock *new_fl, *new_fl2;
         struct file_lock *left = NULL;
         struct file_lock *right = NULL;
         struct file_lock **before;
- struct inode * inode = filp->f_dentry->d_inode;
         int error, added = 0;
 
         /*
@@ -1460,7 +1467,7 @@
         }
 
         for (;;) {
- error = posix_lock_file(filp, file_lock);
+ error = posix_lock_file(inode, file_lock);
                 if ((error != -EAGAIN) || (cmd == F_SETLK))
                         break;
                 error = wait_event_interruptible(file_lock->fl_wait,
@@ -1600,7 +1607,7 @@
         }
 
         for (;;) {
- error = posix_lock_file(filp, file_lock);
+ error = posix_lock_file(inode, file_lock);
                 if ((error != -EAGAIN) || (cmd == F_SETLK64))
                         break;
                 error = wait_event_interruptible(file_lock->fl_wait,
@@ -1650,7 +1657,7 @@
                 /* Ignore any error -- we must remove the locks anyway */
         }
 
- posix_lock_file(filp, &lock);
+ posix_lock_file(filp->f_dentry->d_inode, &lock);
 }
 
 /*
@@ -1717,7 +1724,7 @@
         } else {
                 unlock_kernel();
                 waiter->fl_type = F_UNLCK;
- posix_lock_file(filp, waiter);
+ posix_lock_file(filp->f_dentry->d_inode, waiter);
         }
 }
 
diff -uNr linux-2.5.59-vanilla/include/linux/fs.h linux-2.5.59/include/linux/fs.h
--- linux-2.5.59-vanilla/include/linux/fs.h Thu Jan 23 00:02:44 2003
+++ linux-2.5.59/include/linux/fs.h Thu Jan 23 00:48:25 2003
@@ -568,7 +568,7 @@
 extern void locks_remove_posix(struct file *, fl_owner_t);
 extern void locks_remove_flock(struct file *);
 extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
-extern int posix_lock_file(struct file *, struct file_lock *);
+extern int posix_lock_file(struct inode *, struct file_lock *);
 extern void posix_block_lock(struct file_lock *, struct file_lock *);
 extern void posix_unblock_lock(struct file *, struct file_lock *);
 extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jan 23 2003 - 22:00:30 EST