Skip to content

Commit 2ec197d

Browse files
neilbrownJ. Bruce Fields
authored andcommitted
lockd: send correct lock when granting a delayed lock.
If an NFS client attempts to get a lock (using NLM) and the lock is not available, the server will remember the request and when the lock becomes available it will send a GRANT request to the client to provide the lock. If the client already held an adjacent lock, the GRANT callback will report the union of the existing and new locks, which can confuse the client. This happens because __posix_lock_file (called by vfs_lock_file) updates the passed-in file_lock structure when adjacent or over-lapping locks are found. To avoid this problem we take a copy of the two fields that can be changed (fl_start and fl_end) before the call and restore them afterwards. An alternate would be to allocate a 'struct file_lock', initialise it, use locks_copy_lock() to take a copy, then locks_release_private() after the vfs_lock_file() call. But that is a lot more work. Reported-by: Olaf Kirch <okir@suse.com> Signed-off-by: NeilBrown <neilb@suse.de> Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields <bfields@redhat.com> -- v1 had a couple of issues (large on-stack struct and didn't really work properly). This version is much better tested. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 09bdc2d commit 2ec197d

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

fs/lockd/svclock.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
779779
struct nlm_file *file = block->b_file;
780780
struct nlm_lock *lock = &block->b_call->a_args.lock;
781781
int error;
782+
loff_t fl_start, fl_end;
782783

783784
dprintk("lockd: grant blocked lock %p\n", block);
784785

@@ -796,9 +797,16 @@ nlmsvc_grant_blocked(struct nlm_block *block)
796797
}
797798

798799
/* Try the lock operation again */
800+
/* vfs_lock_file() can mangle fl_start and fl_end, but we need
801+
* them unchanged for the GRANT_MSG
802+
*/
799803
lock->fl.fl_flags |= FL_SLEEP;
804+
fl_start = lock->fl.fl_start;
805+
fl_end = lock->fl.fl_end;
800806
error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
801807
lock->fl.fl_flags &= ~FL_SLEEP;
808+
lock->fl.fl_start = fl_start;
809+
lock->fl.fl_end = fl_end;
802810

803811
switch (error) {
804812
case 0:

0 commit comments

Comments
 (0)