summaryrefslogtreecommitdiff
path: root/fs/locks.c
diff options
context:
space:
mode:
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,
}
/* 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;