Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.24.7 /fs/locks.c

Filename:/fs/locks.c
Lines Added:43
Lines Deleted:22
Also changed in: (Previous) 2.6.24.6  2.6.24.5  2.6.24.5-rc2  2.6.24.5-rc1  2.6.24-git22  2.6.24-git21 
(Following) 2.6.25.3  2.6.25.4  2.6.25.5  2.6.25.6  2.6.25.7  2.6.25.8 

Location
[  2.6.24.7
  [  fs
     o  locks.c

Patch

diff --git a/fs/locks.c b/fs/locks.c
index 8b8388e..7127620 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1754,6 +1754,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
    struct file_lock *file_lock = locks_alloc_lock();
    struct flock flock;
    struct inode *inode;
+   struct file *f;
    int error;
 
    if (file_lock == NULL)
@@ -1805,24 +1806,36 @@ again:
    if (error)
       goto out;
 
-   for (;;) {
-      error = vfs_lock_file(filp, cmd, file_lock, NULL);
-      if (error != -EAGAIN || cmd == F_SETLK)
-         break;
-      error = wait_event_interruptible(file_lock->fl_wait,
-            !file_lock->fl_next);
-      if (!error)
-         continue;
+   if (filp->f_op && filp->f_op->lock != NULL)
+      error = filp->f_op->lock(filp, cmd, file_lock);
+   else {
+      for (;;) {
+         error = posix_lock_file(filp, file_lock, NULL);
+         if (error != -EAGAIN || cmd == F_SETLK)
+            break;
+         error = wait_event_interruptible(file_lock->fl_wait,
+               !file_lock->fl_next);
+         if (!error)
+            continue;
 
-      locks_delete_block(file_lock);
-      break;
+         locks_delete_block(file_lock);
+         break;
+      }
    }
 
    /*
     * Attempt to detect a close/fcntl race and recover by
     * releasing the lock that was just acquired.
     */
-   if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
+   /*
+    * we need that spin_lock here - it prevents reordering between
+    * update of inode->i_flock and check for it done in close().
+    * rcu_read_lock() wouldn't do.
+    */
+   spin_lock(¤t->files->file_lock);
+   f = fcheck(fd);
+   spin_unlock(¤t->files->file_lock);
+   if (!error && f != filp && flock.l_type != F_UNLCK) {
       flock.l_type = F_UNLCK;
       goto again;
    }
@@ -1878,6 +1891,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
    struct file_lock *file_lock = locks_alloc_lock();
    struct flock64 flock;
    struct inode *inode;
+   struct file *f;
    int error;
 
    if (file_lock == NULL)
@@ -1929,24 +1943,31 @@ again:
    if (error)
       goto out;
 
-   for (;;) {
-      error = vfs_lock_file(filp, cmd, file_lock, NULL);
-      if (error != -EAGAIN || cmd == F_SETLK64)
-         break;
-      error = wait_event_interruptible(file_lock->fl_wait,
-            !file_lock->fl_next);
-      if (!error)
-         continue;
+   if (filp->f_op && filp->f_op->lock != NULL)
+      error = filp->f_op->lock(filp, cmd, file_lock);
+   else {
+      for (;;) {
+         error = posix_lock_file(filp, file_lock, NULL);
+         if (error != -EAGAIN || cmd == F_SETLK64)
+            break;
+         error = wait_event_interruptible(file_lock->fl_wait,
+               !file_lock->fl_next);
+         if (!error)
+            continue;
 
-      locks_delete_block(file_lock);
-      break;
+         locks_delete_block(file_lock);
+         break;
+      }
    }
 
    /*
     * Attempt to detect a close/fcntl race and recover by
     * releasing the lock that was just acquired.
     */
-   if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
+   spin_lock(¤t->files->file_lock);
+   f = fcheck(fd);
+   spin_unlock(¤t->files->file_lock);
+   if (!error && f != filp && flock.l_type != F_UNLCK) {
       flock.l_type = F_UNLCK;
       goto again;
    }


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.