aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 5853f53db732..7f3f60641344 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -125,6 +125,8 @@ again:
125 continue; 125 continue;
126 if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) 126 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
127 continue; 127 continue;
128 if (!nfs4_valid_open_stateid(state))
129 continue;
128 if (!nfs4_stateid_match(&state->stateid, stateid)) 130 if (!nfs4_stateid_match(&state->stateid, stateid))
129 continue; 131 continue;
130 get_nfs_open_context(ctx); 132 get_nfs_open_context(ctx);
@@ -193,7 +195,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
193{ 195{
194 int res = 0; 196 int res = 0;
195 197
196 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); 198 if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
199 res = nfs4_proc_delegreturn(inode,
200 delegation->cred,
201 &delegation->stateid,
202 issync);
197 nfs_free_delegation(delegation); 203 nfs_free_delegation(delegation);
198 return res; 204 return res;
199} 205}
@@ -380,11 +386,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
380{ 386{
381 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 387 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
382 struct nfs_inode *nfsi = NFS_I(inode); 388 struct nfs_inode *nfsi = NFS_I(inode);
383 int err; 389 int err = 0;
384 390
385 if (delegation == NULL) 391 if (delegation == NULL)
386 return 0; 392 return 0;
387 do { 393 do {
394 if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
395 break;
388 err = nfs_delegation_claim_opens(inode, &delegation->stateid); 396 err = nfs_delegation_claim_opens(inode, &delegation->stateid);
389 if (!issync || err != -EAGAIN) 397 if (!issync || err != -EAGAIN)
390 break; 398 break;
@@ -605,10 +613,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl
605 rcu_read_unlock(); 613 rcu_read_unlock();
606} 614}
607 615
616static void nfs_revoke_delegation(struct inode *inode)
617{
618 struct nfs_delegation *delegation;
619 rcu_read_lock();
620 delegation = rcu_dereference(NFS_I(inode)->delegation);
621 if (delegation != NULL) {
622 set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
623 nfs_mark_return_delegation(NFS_SERVER(inode), delegation);
624 }
625 rcu_read_unlock();
626}
627
608void nfs_remove_bad_delegation(struct inode *inode) 628void nfs_remove_bad_delegation(struct inode *inode)
609{ 629{
610 struct nfs_delegation *delegation; 630 struct nfs_delegation *delegation;
611 631
632 nfs_revoke_delegation(inode);
612 delegation = nfs_inode_detach_delegation(inode); 633 delegation = nfs_inode_detach_delegation(inode);
613 if (delegation) { 634 if (delegation) {
614 nfs_inode_find_state_and_recover(inode, &delegation->stateid); 635 nfs_inode_find_state_and_recover(inode, &delegation->stateid);