mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-06 09:56:25 -04:00
nfsd: avoid races with wake_up_var()
wake_up_var() needs a barrier after the important change is made in the var and before wake_up_var() is called, else it is possible that a wake up won't be sent when it should. In each case here the var is changed in an "atomic" manner, so smb_mb__after_atomic() is sufficient. In one case the important change (removing the lease) is performed *after* the wake_up, which is backwards. The code survives in part because the wait_var_event is given a timeout. This patch adds the required barriers and calls destroy_delegation() *before* waking any threads waiting for the delegation to be destroyed. Signed-off-by: NeilBrown <neilb@suse.de> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
@@ -4706,6 +4706,7 @@ void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate)
|
||||
if (so != NULL) {
|
||||
cstate->replay_owner = NULL;
|
||||
atomic_set(&so->so_replay.rp_locked, RP_UNLOCKED);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_var(&so->so_replay.rp_locked);
|
||||
nfs4_put_stateowner(so);
|
||||
}
|
||||
@@ -5006,6 +5007,7 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net)
|
||||
* so tell them to stop waiting.
|
||||
*/
|
||||
atomic_set(&oo->oo_owner.so_replay.rp_locked, RP_UNHASHED);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_var(&oo->oo_owner.so_replay.rp_locked);
|
||||
wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2);
|
||||
|
||||
@@ -7475,8 +7477,9 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
goto put_stateid;
|
||||
|
||||
trace_nfsd_deleg_return(stateid);
|
||||
wake_up_var(d_inode(cstate->current_fh.fh_dentry));
|
||||
destroy_delegation(dp);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_var(d_inode(cstate->current_fh.fh_dentry));
|
||||
put_stateid:
|
||||
nfs4_put_stid(&dp->dl_stid);
|
||||
out:
|
||||
|
||||
Reference in New Issue
Block a user