nfsd: replace rp_mutex to avoid deadlock in move_to_close_lru()
authorNeilBrown <neilb@suse.de>
Mon, 8 Apr 2024 02:09:17 +0000 (12:09 +1000)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 6 May 2024 13:07:16 +0000 (09:07 -0400)
commiteec7620800081e27dbf8019ac2e66259f0d5bf6f
treedddf4b7cae4bee44dc0bae09c66730629203d31a
parentb3f03739ca8cd6058a5d8754ea1354bc21fa0f2f
nfsd: replace rp_mutex to avoid deadlock in move_to_close_lru()

move_to_close_lru() waits for sc_count to become zero while holding
rp_mutex.  This can deadlock if another thread holds a reference and is
waiting for rp_mutex.

By the time we get to move_to_close_lru() the openowner is unhashed and
cannot be found any more.  So code waiting for the mutex can safely
retry the lookup if move_to_close_lru() has started.

So change rp_mutex to an atomic_t with three states:

 RP_UNLOCK   - state is still hashed, not locked for reply
 RP_LOCKED   - state is still hashed, is locked for reply
 RP_UNHASHED - state is not hashed, no code can get a lock.

Use wait_var_event() to wait for either a lock, or for the owner to be
unhashed.  In the latter case, retry the lookup.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4state.c
fs/nfsd/state.h