All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jeff.layton@primarydata.com>
To: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>,
	"Kirill A. Shutemov" <kirill@shutemov.name>,
	"J. Bruce Fields" <bfields@fieldses.org>,
	Christoph Hellwig <hch@lst.de>,
	Dave Chinner <david@fromorbit.com>,
	Sasha Levin <sasha.levin@oracle.com>
Subject: [PATCH 3/4] locks: when upgrading, don't remove old flock lock until replacing with new one
Date: Tue, 17 Feb 2015 07:46:29 -0500	[thread overview]
Message-ID: <1424177190-14252-4-git-send-email-jeff.layton@primarydata.com> (raw)
In-Reply-To: <1424177190-14252-1-git-send-email-jeff.layton@primarydata.com>

There is a potential problem when upgrading a flock lock. Suppose we
have a LOCK_SH lock on a file, and then want to upgrade it to a LOCK_EX
lock. We go through the first loop in flock_lock_file, and remove the
first lock.

We then go through the second loop and try to insert a new LOCK_EX lock.
If however, there is another LOCK_SH lock on the file, we're out of
luck. We've removed our LOCK_SH lock already and can't insert a LOCK_EX
lock.

Fix this by ensuring that we don't remove any lock that we're replacing
until we're sure that we can add its replacement.

Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
---
 fs/locks.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index 00c105f499a2..59eadd416b8c 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -864,13 +864,16 @@ 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 *old_fl = NULL;
 	struct file_lock *fl;
 	struct file_lock_context *ctx;
 	struct inode *inode = file_inode(filp);
 	int error = 0;
-	bool found = false;
 	LIST_HEAD(dispose);
 
+	/* flock_locks_conflict relies on this */
+	WARN_ON_ONCE(request->fl_file != filp);
+
 	ctx = locks_get_lock_context(inode);
 	if (!ctx)
 		return -ENOMEM;
@@ -885,22 +888,29 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
 	if (request->fl_flags & FL_ACCESS)
 		goto find_conflict;
 
+	/*
+	 * Do we already hold a lock on this filp? It may be upgradeable, or it
+	 * may be just what we need.
+	 */
 	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
 		if (filp != fl->fl_file)
 			continue;
 		if (request->fl_type == fl->fl_type)
 			goto out;
-		found = true;
-		locks_delete_lock_ctx(fl, &dispose);
+		old_fl = fl;
 		break;
 	}
 
 	if (request->fl_type == F_UNLCK) {
-		if ((request->fl_flags & FL_EXISTS) && !found)
-			error = -ENOENT;
+		if (old_fl) {
+			locks_delete_lock_ctx(old_fl, &dispose);
+			if (request->fl_flags & FL_EXISTS)
+				error = -ENOENT;
+		}
 		goto out;
 	}
 
+	/* SETLK(W) */
 find_conflict:
 	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
 		if (!flock_locks_conflict(request, fl))
@@ -915,6 +925,8 @@ find_conflict:
 	if (request->fl_flags & FL_ACCESS)
 		goto out;
 	locks_copy_lock(new_fl, request);
+	if (old_fl)
+		locks_delete_lock_ctx(old_fl, &dispose);
 	locks_insert_lock_ctx(new_fl, &ctx->flc_flock);
 	new_fl = NULL;
 	error = 0;
-- 
2.1.0


  parent reply	other threads:[~2015-02-17 12:50 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-17 12:46 [PATCH 0/4] locks: flock and lease related bugfixes, and remove i_flctx counters Jeff Layton
2015-02-17 12:46 ` [PATCH 1/4] Revert "locks: keep a count of locks on the flctx lists" Jeff Layton
2015-02-17 12:46 ` [PATCH 2/4] locks: remove conditional lock release in middle of flock_lock_file Jeff Layton
2015-02-17 17:10   ` J. Bruce Fields
2015-02-17 17:56     ` Jeff Layton
2015-02-17 19:11       ` J. Bruce Fields
2015-02-17 22:21         ` J. Bruce Fields
2015-02-17 22:29           ` Jeff Layton
2015-02-17 12:46 ` Jeff Layton [this message]
2015-02-17 12:46 ` [PATCH 4/4] locks: only remove leases associated with the file being closed Jeff Layton
2015-02-17 19:55 ` [PATCH 0/4] locks: flock and lease related bugfixes, and remove i_flctx counters Linus Torvalds
2015-02-17 20:20   ` Linus Torvalds
2015-02-17 20:20   ` Al Viro
2015-02-17 21:10     ` Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1424177190-14252-4-git-send-email-jeff.layton@primarydata.com \
    --to=jeff.layton@primarydata.com \
    --cc=bfields@fieldses.org \
    --cc=david@fromorbit.com \
    --cc=hch@lst.de \
    --cc=kirill@shutemov.name \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sasha.levin@oracle.com \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.