diff options
| author | Filipe Brandenburger <filbranden@gmail.com> | 2012-07-27 00:42:52 -0400 | 
|---|---|---|
| committer | J. Bruce Fields <bfields@redhat.com> | 2012-07-27 09:39:55 -0400 | 
| commit | 3b6e2723f32de42028617f2c99b244ccd72cd959 (patch) | |
| tree | aa16a8fdef80496ef394aa75c1d5cf9fd137252d | |
| parent | 57c8b13e3cd0f94944c9691ce7f58e5fcef8a12d (diff) | |
| download | olio-linux-3.10-3b6e2723f32de42028617f2c99b244ccd72cd959.tar.xz olio-linux-3.10-3b6e2723f32de42028617f2c99b244ccd72cd959.zip  | |
locks: prevent side-effects of locks_release_private before file_lock is initialized
When calling fcntl(fd, F_SETLEASE, lck) [with lck=F_WRLCK or F_RDLCK],
the custom signal or owner (if any were previously set using F_SETSIG
or F_SETOWN fcntls) would be reset when F_SETLEASE was called for the
second time on the same file descriptor.
This bug is a regression of 2.6.37 and is described here:
https://bugzilla.kernel.org/show_bug.cgi?id=43336
This patch reverts a commit from Oct 2004 (with subject "nfs4 lease:
move the f_delown processing") which originally introduced the
lm_release_private callback.
Signed-off-by: Filipe Brandenburger <filbranden@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
| -rw-r--r-- | fs/locks.c | 17 | 
1 files changed, 6 insertions, 11 deletions
diff --git a/fs/locks.c b/fs/locks.c index 814c51d0de4..86668dd211a 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -427,18 +427,8 @@ static void lease_break_callback(struct file_lock *fl)  	kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);  } -static void lease_release_private_callback(struct file_lock *fl) -{ -	if (!fl->fl_file) -		return; - -	f_delown(fl->fl_file); -	fl->fl_file->f_owner.signum = 0; -} -  static const struct lock_manager_operations lease_manager_ops = {  	.lm_break = lease_break_callback, -	.lm_release_private = lease_release_private_callback,  	.lm_change = lease_modify,  }; @@ -1155,8 +1145,13 @@ int lease_modify(struct file_lock **before, int arg)  		return error;  	lease_clear_pending(fl, arg);  	locks_wake_up_blocks(fl); -	if (arg == F_UNLCK) +	if (arg == F_UNLCK) { +		struct file *filp = fl->fl_file; + +		f_delown(filp); +		filp->f_owner.signum = 0;  		locks_delete_lock(before); +	}  	return 0;  }  |