Commit 41020b67 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFSv4.x: Allow callers of nfs_remove_bad_delegation() to specify a stateid

Allow the callers of nfs_remove_bad_delegation() to specify the stateid
that needs to be marked as bad.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Tested-by: default avatarOleg Drokin <green@linuxhacker.ru>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 4586f6e2
...@@ -652,23 +652,39 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl ...@@ -652,23 +652,39 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl
rcu_read_unlock(); rcu_read_unlock();
} }
static void nfs_revoke_delegation(struct inode *inode) static void nfs_mark_delegation_revoked(struct nfs_server *server,
struct nfs_delegation *delegation)
{
set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
nfs_mark_return_delegation(server, delegation);
}
static bool nfs_revoke_delegation(struct inode *inode,
const nfs4_stateid *stateid)
{ {
struct nfs_delegation *delegation; struct nfs_delegation *delegation;
bool ret = false;
rcu_read_lock(); rcu_read_lock();
delegation = rcu_dereference(NFS_I(inode)->delegation); delegation = rcu_dereference(NFS_I(inode)->delegation);
if (delegation != NULL) { if (delegation == NULL)
set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); goto out;
nfs_mark_return_delegation(NFS_SERVER(inode), delegation); if (stateid && !nfs4_stateid_match(stateid, &delegation->stateid))
} goto out;
nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
ret = true;
out:
rcu_read_unlock(); rcu_read_unlock();
return ret;
} }
void nfs_remove_bad_delegation(struct inode *inode) void nfs_remove_bad_delegation(struct inode *inode,
const nfs4_stateid *stateid)
{ {
struct nfs_delegation *delegation; struct nfs_delegation *delegation;
nfs_revoke_delegation(inode); if (!nfs_revoke_delegation(inode, stateid))
return;
delegation = nfs_inode_detach_delegation(inode); delegation = nfs_inode_detach_delegation(inode);
if (delegation) { if (delegation) {
nfs_inode_find_state_and_recover(inode, &delegation->stateid); nfs_inode_find_state_and_recover(inode, &delegation->stateid);
......
...@@ -47,7 +47,7 @@ void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags); ...@@ -47,7 +47,7 @@ void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags);
void nfs_expire_unreferenced_delegations(struct nfs_client *clp); void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
int nfs_client_return_marked_delegations(struct nfs_client *clp); int nfs_client_return_marked_delegations(struct nfs_client *clp);
int nfs_delegations_present(struct nfs_client *clp); int nfs_delegations_present(struct nfs_client *clp);
void nfs_remove_bad_delegation(struct inode *inode); void nfs_remove_bad_delegation(struct inode *inode, const nfs4_stateid *stateid);
void nfs_delegation_mark_reclaim(struct nfs_client *clp); void nfs_delegation_mark_reclaim(struct nfs_client *clp);
void nfs_delegation_reap_unclaimed(struct nfs_client *clp); void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
......
...@@ -1080,7 +1080,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, ...@@ -1080,7 +1080,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BAD_STATEID:
if (state == NULL) if (state == NULL)
break; break;
nfs_remove_bad_delegation(state->inode); nfs_remove_bad_delegation(state->inode, NULL);
case -NFS4ERR_OPENMODE: case -NFS4ERR_OPENMODE:
if (state == NULL) if (state == NULL)
break; break;
......
...@@ -2385,9 +2385,10 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta ...@@ -2385,9 +2385,10 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
return ret; return ret;
} }
static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state,
const nfs4_stateid *stateid)
{ {
nfs_remove_bad_delegation(state->inode); nfs_remove_bad_delegation(state->inode, stateid);
write_seqlock(&state->seqlock); write_seqlock(&state->seqlock);
nfs4_stateid_copy(&state->stateid, &state->open_stateid); nfs4_stateid_copy(&state->stateid, &state->open_stateid);
write_sequnlock(&state->seqlock); write_sequnlock(&state->seqlock);
...@@ -2397,7 +2398,7 @@ static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) ...@@ -2397,7 +2398,7 @@ static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state)
static void nfs40_clear_delegation_stateid(struct nfs4_state *state) static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
{ {
if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
nfs_finish_clear_delegation_stateid(state); nfs_finish_clear_delegation_stateid(state, NULL);
} }
static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
...@@ -2443,19 +2444,20 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state) ...@@ -2443,19 +2444,20 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
rcu_read_unlock(); rcu_read_unlock();
return; return;
} }
nfs4_stateid_copy(&stateid, &delegation->stateid);
if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) { if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
rcu_read_unlock(); rcu_read_unlock();
nfs_finish_clear_delegation_stateid(state); nfs_finish_clear_delegation_stateid(state, &stateid);
return; return;
} }
nfs4_stateid_copy(&stateid, &delegation->stateid);
cred = get_rpccred(delegation->cred); cred = get_rpccred(delegation->cred);
rcu_read_unlock(); rcu_read_unlock();
status = nfs41_test_and_free_expired_stateid(server, &stateid, cred); status = nfs41_test_and_free_expired_stateid(server, &stateid, cred);
trace_nfs4_test_delegation_stateid(state, NULL, status); trace_nfs4_test_delegation_stateid(state, NULL, status);
if (status != NFS_OK) if (status != NFS_OK)
nfs_finish_clear_delegation_stateid(state); nfs_finish_clear_delegation_stateid(state, &stateid);
put_rpccred(cred); put_rpccred(cred);
} }
......
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