aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-09-01 15:06:54 -0400
committerJeff Layton <jlayton@primarydata.com>2014-10-07 14:06:13 -0400
commit4d01b7f5e7576858b71cbaa72b541e17a229cb91 (patch)
tree5ea9a839335ca6159ac24f1cf5ddfbe3ff1e7c74 /fs/locks.c
parent03d12ddf845a4eb874ffa558d65a548aee9b715b (diff)
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.c17
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,
427} 427}
428 428
429/* default lease lock manager operations */ 429/* default lease lock manager operations */
430static void lease_break_callback(struct file_lock *fl) 430static bool
431lease_break_callback(struct file_lock *fl)
431{ 432{
432 kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); 433 kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
434 return false;
433} 435}
434 436
435static void 437static void
@@ -1382,7 +1384,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1382{ 1384{
1383 int error = 0; 1385 int error = 0;
1384 struct file_lock *new_fl; 1386 struct file_lock *new_fl;
1385 struct file_lock *fl; 1387 struct file_lock *fl, **before;
1386 unsigned long break_time; 1388 unsigned long break_time;
1387 int want_write = (mode & O_ACCMODE) != O_RDONLY; 1389 int want_write = (mode & O_ACCMODE) != O_RDONLY;
1388 LIST_HEAD(dispose); 1390 LIST_HEAD(dispose);
@@ -1406,7 +1408,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1406 break_time++; /* so that 0 means no break time */ 1408 break_time++; /* so that 0 means no break time */
1407 } 1409 }
1408 1410
1409 for (fl = inode->i_flock; fl && IS_LEASE(fl); fl = fl->fl_next) { 1411 for (before = &inode->i_flock;
1412 ((fl = *before) != NULL) && IS_LEASE(fl);
1413 before = &fl->fl_next) {
1410 if (!leases_conflict(fl, new_fl)) 1414 if (!leases_conflict(fl, new_fl))
1411 continue; 1415 continue;
1412 if (want_write) { 1416 if (want_write) {
@@ -1420,9 +1424,14 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1420 fl->fl_flags |= FL_DOWNGRADE_PENDING; 1424 fl->fl_flags |= FL_DOWNGRADE_PENDING;
1421 fl->fl_downgrade_time = break_time; 1425 fl->fl_downgrade_time = break_time;
1422 } 1426 }
1423 fl->fl_lmops->lm_break(fl); 1427 if (fl->fl_lmops->lm_break(fl))
1428 locks_delete_lock(before, &dispose);
1424 } 1429 }
1425 1430
1431 fl = inode->i_flock;
1432 if (!fl || !IS_LEASE(fl))
1433 goto out;
1434
1426 if (mode & O_NONBLOCK) { 1435 if (mode & O_NONBLOCK) {
1427 trace_break_lease_noblock(inode, new_fl); 1436 trace_break_lease_noblock(inode, new_fl);
1428 error = -EWOULDBLOCK; 1437 error = -EWOULDBLOCK;