Commit d75a6a0e authored by Benjamin Coddington's avatar Benjamin Coddington Committed by Anna Schumaker

NFSv4.1: Keep a reference on lock states while checking

While walking the list of lock_states, keep a reference on each
nfs4_lock_state to be checked, otherwise the lock state could be removed
while the check performs TEST_STATEID and possible FREE_STATEID.
Signed-off-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent d41cbfc9
...@@ -2564,15 +2564,23 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state) ...@@ -2564,15 +2564,23 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
static int nfs41_check_expired_locks(struct nfs4_state *state) static int nfs41_check_expired_locks(struct nfs4_state *state)
{ {
int status, ret = NFS_OK; int status, ret = NFS_OK;
struct nfs4_lock_state *lsp; struct nfs4_lock_state *lsp, *prev = NULL;
struct nfs_server *server = NFS_SERVER(state->inode); struct nfs_server *server = NFS_SERVER(state->inode);
if (!test_bit(LK_STATE_IN_USE, &state->flags)) if (!test_bit(LK_STATE_IN_USE, &state->flags))
goto out; goto out;
spin_lock(&state->state_lock);
list_for_each_entry(lsp, &state->lock_states, ls_locks) { list_for_each_entry(lsp, &state->lock_states, ls_locks) {
if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
struct rpc_cred *cred = lsp->ls_state->owner->so_cred; struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
atomic_inc(&lsp->ls_count);
spin_unlock(&state->state_lock);
nfs4_put_lock_state(prev);
prev = lsp;
status = nfs41_test_and_free_expired_stateid(server, status = nfs41_test_and_free_expired_stateid(server,
&lsp->ls_stateid, &lsp->ls_stateid,
cred); cred);
...@@ -2585,10 +2593,14 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) ...@@ -2585,10 +2593,14 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
set_bit(NFS_LOCK_LOST, &lsp->ls_flags); set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
} else if (status != NFS_OK) { } else if (status != NFS_OK) {
ret = status; ret = status;
break; nfs4_put_lock_state(prev);
goto out;
} }
spin_lock(&state->state_lock);
} }
}; }
spin_unlock(&state->state_lock);
nfs4_put_lock_state(prev);
out: out:
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment