locks: don't reuse file_lock in __posix_lock_file

Currently in the case where a new file lock completely replaces the old
one, we end up overwriting the existing lock with the new info. This
means that we have to call fl_release_private inside i_lock. Change the
code to instead copy the info to new_fl, insert that lock into the
correct spot and then delete the old lock. In a later patch, we'll defer
the freeing of the old lock until after the i_lock has been dropped.

Acked-by: J. Bruce Fields <bfields@fieldses.org>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
This commit is contained in:
Jeff Layton 2014-08-12 08:03:49 -04:00
parent 566709bd62
commit b84d49f944
1 changed files with 14 additions and 11 deletions

View File

@ -1022,18 +1022,21 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
locks_delete_lock(before); locks_delete_lock(before);
continue; continue;
} }
/* Replace the old lock with the new one. /*
* Wake up anybody waiting for the old one, * Replace the old lock with new_fl, and
* as the change in lock type might satisfy * remove the old one. It's safe to do the
* their needs. * insert here since we know that we won't be
* using new_fl later, and that the lock is
* just replacing an existing lock.
*/ */
locks_wake_up_blocks(fl); error = -ENOLCK;
fl->fl_start = request->fl_start; if (!new_fl)
fl->fl_end = request->fl_end; goto out;
fl->fl_type = request->fl_type; locks_copy_lock(new_fl, request);
locks_release_private(fl); request = new_fl;
locks_copy_private(fl, request); new_fl = NULL;
request = fl; locks_delete_lock(before);
locks_insert_lock(before, request);
added = true; added = true;
} }
} }