[PATCH] locks: ensure that we can't set multiple flock locks for the same filp

From: Jeff Layton
Date: Tue Feb 17 2015 - 15:08:06 EST

Currently, we'll drop the spinlock in the middle of flock_lock_file in
the event that we found an lock that needed to be removed prior to an
upgrade or downgrade.

It's possible however for another task to race in and set a lock on
the same filp. If that happens, then we don't want to set an additional
lock, so just remove the one that raced in and set our own.

Signed-off-by: Jeff Layton <jeff.layton@xxxxxxxxxxxxxxx>
fs/locks.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index fe8f9f46445b..099b60a46ccc 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -864,7 +864,7 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
static int flock_lock_file(struct file *filp, struct file_lock *request)
struct file_lock *new_fl = NULL;
- struct file_lock *fl;
+ struct file_lock *fl, *tmp;
struct file_lock_context *ctx;
struct inode *inode = file_inode(filp);
int error = 0;
@@ -912,7 +912,12 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)

- list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
+ list_for_each_entry_safe(fl, tmp, &ctx->flc_flock, fl_list) {
+ /* did someone set a lock on the same filp? */
+ if (fl->fl_file == filp) {
+ locks_delete_lock_ctx(fl, &dispose);
+ continue;
+ }
if (!flock_locks_conflict(request, fl))
error = -EAGAIN;

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/