VFS: Allow caller to determine if BSD or posix locks were actually freed From: Trond Myklebust 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 --- fs/locks.c | 18 ++++++++++++++++-- include/linux/fs.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 6f99c0a..72f9f63 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -727,6 +727,10 @@ EXPORT_SYMBOL(posix_locks_deadlock); /* 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) { @@ -752,8 +756,11 @@ static int flock_lock_file(struct file * break; } - if (request->fl_type == F_UNLCK) + if (request->fl_type == F_UNLCK) { + if ((request->fl_flags & FL_EXISTS) && !found) + error = -ENOENT; goto out; + } new_fl = locks_alloc_lock(); if (new_fl == NULL) @@ -938,8 +945,11 @@ static int __posix_lock_file_conf(struct 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; + } locks_copy_lock(new_fl, request); locks_insert_lock(before, new_fl); new_fl = NULL; @@ -981,6 +991,10 @@ static int __posix_lock_file_conf(struct * 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) { diff --git a/include/linux/fs.h b/include/linux/fs.h index f813bc8..6139bf0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -682,6 +682,7 @@ #endif #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_SLEEP 128 /* A blocking lock */