diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2007-09-12 18:56:12 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-10-09 18:31:57 -0400 |
commit | 0272e1fd9f4fa8a43357c168e081744f99e67195 (patch) | |
tree | c56c6469fd2d220e317cf7ab7215e538dca5bad3 | |
parent | 354ecbb9dd89c21708b319da8c4ffd3dd6e6811d (diff) |
knfsd: let nfsd manage timing out its own leases
Currently there's a race that can cause an oops in generic_setlease.
(In detail: nfsd, when it removes a lease, does so by calling
vfs_setlease() with F_UNLCK and a pointer to the fl_flock field, which
in turn points to nfsd's existing lease; but the first thing the
setlease code does is call time_out_leases(). If the lease happens to
already be beyond the lease break time, that will free the lease and (in
nfsd's release_private callback) set fl_flock to NULL, leading to a NULL
deference soon after in vfs_setlease().)
There are probably other things to fix here too, but it seems inherently
racy to allow either locks.c or nfsd to time out this lease. Instead
just set the fl_break_time to 0 (preventing locks.c from ever timing out
this lock) and leave it up to nfsd's laundromat thread to deal with it.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | fs/nfsd/nfs4state.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 6256492b2363..48fbdac33c7c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1354,8 +1354,12 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
1354 | /* only place dl_time is set. protected by lock_kernel*/ | 1354 | /* only place dl_time is set. protected by lock_kernel*/ |
1355 | dp->dl_time = get_seconds(); | 1355 | dp->dl_time = get_seconds(); |
1356 | 1356 | ||
1357 | /* XXX need to merge NFSD_LEASE_TIME with fs/locks.c:lease_break_time */ | 1357 | /* |
1358 | fl->fl_break_time = jiffies + NFSD_LEASE_TIME * HZ; | 1358 | * We don't want the locks code to timeout the lease for us; |
1359 | * we'll remove it ourself if the delegation isn't returned | ||
1360 | * in time. | ||
1361 | */ | ||
1362 | fl->fl_break_time = 0; | ||
1359 | 1363 | ||
1360 | t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); | 1364 | t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); |
1361 | if (IS_ERR(t)) { | 1365 | if (IS_ERR(t)) { |