VFS: Allow caller to determine if BSD or posix locks were actually freed
Trond Myklebust [Thu, 29 Jun 2006 20:38:32 +0000 (16:38 -0400)]
Change posix_lock_file_conf(), and flock_lock_file() so that if called
with an F_UNLCK argument, and the FL_EXISTS flag they will indicate
whether or not any locks were actually freed by returning 0 or -ENOENT.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

fs/locks.c
include/linux/fs.h

index 1ad29c9..50cb0a2 100644 (file)
@@ -725,6 +725,10 @@ next_task:
 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
  * at the head of the list, but that's secret knowledge known only to
  * flock_lock_file and posix_lock_file.
+ *
+ * Note that if called with an FL_EXISTS argument, the caller may determine
+ * whether or not a lock was successfully freed by testing the return
+ * value for -ENOENT.
  */
 static int flock_lock_file(struct file *filp, struct file_lock *request)
 {
@@ -750,8 +754,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
                break;
        }
 
-       if (request->fl_type == F_UNLCK)
+       if (request->fl_type == F_UNLCK) {
+               if ((request->fl_flags & FL_EXISTS) && !found)
+                       error = -ENOENT;
                goto out;
+       }
 
        error = -ENOMEM;
        new_fl = locks_alloc_lock();
@@ -948,8 +955,11 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
 
        error = 0;
        if (!added) {
-               if (request->fl_type == F_UNLCK)
+               if (request->fl_type == F_UNLCK) {
+                       if (request->fl_flags & FL_EXISTS)
+                               error = -ENOENT;
                        goto out;
+               }
 
                if (!new_fl) {
                        error = -ENOLCK;
@@ -996,6 +1006,10 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
  * Add a POSIX style lock to a file.
  * We merge adjacent & overlapping locks whenever possible.
  * POSIX locks are sorted by owner task, then by starting address
+ *
+ * Note that if called with an FL_EXISTS argument, the caller may determine
+ * whether or not a lock was successfully freed by testing the return
+ * value for -ENOENT.
  */
 int posix_lock_file(struct file *filp, struct file_lock *fl)
 {
index 134b320..43aef9b 100644 (file)
@@ -716,6 +716,7 @@ extern spinlock_t files_lock;
 #define FL_POSIX       1
 #define FL_FLOCK       2
 #define FL_ACCESS      8       /* not trying to lock, just looking */
+#define FL_EXISTS      16      /* when unlocking, test for existence */
 #define FL_LEASE       32      /* lease held on this file */
 #define FL_CLOSE       64      /* unlock on close */
 #define FL_SLEEP       128     /* A blocking lock */