Skip to content

Commit 15392c8

Browse files
neilbrownchucklever
authored andcommitted
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 <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 985eeae commit 15392c8

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

fs/nfsd/nfs4state.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4706,6 +4706,7 @@ void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate)
47064706
if (so != NULL) {
47074707
cstate->replay_owner = NULL;
47084708
atomic_set(&so->so_replay.rp_locked, RP_UNLOCKED);
4709+
smp_mb__after_atomic();
47094710
wake_up_var(&so->so_replay.rp_locked);
47104711
nfs4_put_stateowner(so);
47114712
}
@@ -5006,6 +5007,7 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net)
50065007
* so tell them to stop waiting.
50075008
*/
50085009
atomic_set(&oo->oo_owner.so_replay.rp_locked, RP_UNHASHED);
5010+
smp_mb__after_atomic();
50095011
wake_up_var(&oo->oo_owner.so_replay.rp_locked);
50105012
wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2);
50115013

@@ -7475,8 +7477,9 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
74757477
goto put_stateid;
74767478

74777479
trace_nfsd_deleg_return(stateid);
7478-
wake_up_var(d_inode(cstate->current_fh.fh_dentry));
74797480
destroy_delegation(dp);
7481+
smp_mb__after_atomic();
7482+
wake_up_var(d_inode(cstate->current_fh.fh_dentry));
74807483
put_stateid:
74817484
nfs4_put_stid(&dp->dl_stid);
74827485
out:

0 commit comments

Comments
 (0)