diff options
author | Jeff Layton <jlayton@primarydata.com> | 2014-09-01 15:06:54 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@primarydata.com> | 2014-10-07 14:06:13 -0400 |
commit | 4d01b7f5e7576858b71cbaa72b541e17a229cb91 (patch) | |
tree | 5ea9a839335ca6159ac24f1cf5ddfbe3ff1e7c74 /fs/locks.c | |
parent | 03d12ddf845a4eb874ffa558d65a548aee9b715b (diff) | |
download | linux-stable-4d01b7f5e7576858b71cbaa72b541e17a229cb91.tar.gz linux-stable-4d01b7f5e7576858b71cbaa72b541e17a229cb91.tar.bz2 linux-stable-4d01b7f5e7576858b71cbaa72b541e17a229cb91.zip |
locks: give lm_break a return value
Christoph suggests:
"Add a return value to lm_break so that the lock manager can tell the
core code "you can delete this lease right now". That gets rid of
the games with the timeout which require all kinds of race avoidance
code in the users."
Do that here and have the nfsd lease break routine use it when it detects
that there was a race between setting up the lease and it being broken.
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/locks.c b/fs/locks.c index 7d627ac0ed87..aed4a957d232 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -427,9 +427,11 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, } /* default lease lock manager operations */ -static void lease_break_callback(struct file_lock *fl) +static bool +lease_break_callback(struct file_lock *fl) { kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); + return false; } static void @@ -1382,7 +1384,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) { int error = 0; struct file_lock *new_fl; - struct file_lock *fl; + struct file_lock *fl, **before; unsigned long break_time; int want_write = (mode & O_ACCMODE) != O_RDONLY; LIST_HEAD(dispose); @@ -1406,7 +1408,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) break_time++; /* so that 0 means no break time */ } - for (fl = inode->i_flock; fl && IS_LEASE(fl); fl = fl->fl_next) { + for (before = &inode->i_flock; + ((fl = *before) != NULL) && IS_LEASE(fl); + before = &fl->fl_next) { if (!leases_conflict(fl, new_fl)) continue; if (want_write) { @@ -1420,9 +1424,14 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) fl->fl_flags |= FL_DOWNGRADE_PENDING; fl->fl_downgrade_time = break_time; } - fl->fl_lmops->lm_break(fl); + if (fl->fl_lmops->lm_break(fl)) + locks_delete_lock(before, &dispose); } + fl = inode->i_flock; + if (!fl || !IS_LEASE(fl)) + goto out; + if (mode & O_NONBLOCK) { trace_break_lease_noblock(inode, new_fl); error = -EWOULDBLOCK; |