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: Trond Myklebust <trond.myklebust@primarydata.com> Tested-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
committed by
Anna Schumaker
parent
4586f6e283
commit
41020b671a
@@ -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)
|
||||||
{
|
{
|
||||||
struct nfs_delegation *delegation;
|
|
||||||
rcu_read_lock();
|
|
||||||
delegation = rcu_dereference(NFS_I(inode)->delegation);
|
|
||||||
if (delegation != NULL) {
|
|
||||||
set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
|
set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
|
||||||
nfs_mark_return_delegation(NFS_SERVER(inode), delegation);
|
nfs_mark_return_delegation(server, delegation);
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_remove_bad_delegation(struct inode *inode)
|
static bool nfs_revoke_delegation(struct inode *inode,
|
||||||
|
const nfs4_stateid *stateid)
|
||||||
|
{
|
||||||
|
struct nfs_delegation *delegation;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
delegation = rcu_dereference(NFS_I(inode)->delegation);
|
||||||
|
if (delegation == NULL)
|
||||||
|
goto out;
|
||||||
|
if (stateid && !nfs4_stateid_match(stateid, &delegation->stateid))
|
||||||
|
goto out;
|
||||||
|
nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
|
||||||
|
ret = true;
|
||||||
|
out:
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
|||||||
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,
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user