mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
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: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
d41cbfc9a6
commit
d75a6a0e39
1 changed files with 15 additions and 3 deletions
|
@ -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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue