locks: fix possible infinite loop in fcntl(F_SETLKW) over nfs
[sfrench/cifs-2.6.git] / fs / locks.c
index f36f0e61558dabfdeb7be02ed245e8bca13c663b..43c0af21a0c5fb563ceb12073d085e5ed45e2ddf 100644 (file)
@@ -1275,13 +1275,13 @@ out:
 EXPORT_SYMBOL(__break_lease);
 
 /**
- *     lease_get_mtime
+ *     lease_get_mtime - get the last modified time of an inode
  *     @inode: the inode
  *      @time:  pointer to a timespec which will contain the last modified time
  *
  * This is to force NFS clients to flush their caches for files with
  * exclusive leases.  The justification is that if someone has an
- * exclusive lease, then they could be modifiying it.
+ * exclusive lease, then they could be modifying it.
  */
 void lease_get_mtime(struct inode *inode, struct timespec *time)
 {
@@ -1801,17 +1801,21 @@ 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;
+               }
        }
 
        /*
@@ -1925,17 +1929,21 @@ 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;
+               }
        }
 
        /*