From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> After setting nfl->nfs_uuid to NULL, dereferences of nfl should be avoided, since there are no further guarantees that the memory is still allocated. Also change the wake_up_var_locked() to be a regular wake_up_var(), since nfs_close_local_fh() cannot retake the nfs_uuid->lock after dropping it. Acked-by: Mike Snitzer <snitzer@xxxxxxxxxx> Tested-by: Mike Snitzer <snitzer@xxxxxxxxxx> Fixes: 21fb44034695 ("nfs_localio: protect race between nfs_uuid_put() and nfs_close_local_fh()") Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> --- fs/nfs_common/nfslocalio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c index d157fdc068d7..27ad5263e400 100644 --- a/fs/nfs_common/nfslocalio.c +++ b/fs/nfs_common/nfslocalio.c @@ -199,8 +199,8 @@ static bool nfs_uuid_put(nfs_uuid_t *nfs_uuid) /* Now we can allow racing nfs_close_local_fh() to * skip the locking. */ - RCU_INIT_POINTER(nfl->nfs_uuid, NULL); - wake_up_var_locked(&nfl->nfs_uuid, &nfs_uuid->lock); + rcu_assign_pointer(nfl->nfs_uuid, NULL); + wake_up_var(nfl); } /* Remove client from nn->local_clients */ @@ -321,8 +321,7 @@ void nfs_close_local_fh(struct nfs_file_localio *nfl) */ spin_unlock(&nfs_uuid->lock); rcu_read_unlock(); - wait_var_event(&nfl->nfs_uuid, - rcu_access_pointer(nfl->nfs_uuid) == NULL); + wait_var_event(nfl, rcu_access_pointer(nfl->nfs_uuid) == NULL); return; } /* tell nfs_uuid_put() to wait for us */ -- 2.50.1