summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-09-22 13:38:58 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-09-27 14:33:37 -0400
commit41020b671aa553f31e766fd1e9d38598eba72bd6 (patch)
tree1733c68445df37fda9424a27bf9866335bcdb47d /fs
parent4586f6e2832776e070cc5eb88c2b2f0177e928ae (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/delegation.c30
-rw-r--r--fs/nfs/delegation.h2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c2
-rw-r--r--fs/nfs/nfs4proc.c14
4 files changed, 33 insertions, 15 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index b9c65421ed81..e5212e5c73d2 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -652,23 +652,39 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl
652 rcu_read_unlock(); 652 rcu_read_unlock();
653} 653}
654 654
655static void nfs_revoke_delegation(struct inode *inode) 655static void nfs_mark_delegation_revoked(struct nfs_server *server,
656 struct nfs_delegation *delegation)
657{
658 set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
659 nfs_mark_return_delegation(server, delegation);
660}
661
662static bool nfs_revoke_delegation(struct inode *inode,
663 const nfs4_stateid *stateid)
656{ 664{
657 struct nfs_delegation *delegation; 665 struct nfs_delegation *delegation;
666 bool ret = false;
667
658 rcu_read_lock(); 668 rcu_read_lock();
659 delegation = rcu_dereference(NFS_I(inode)->delegation); 669 delegation = rcu_dereference(NFS_I(inode)->delegation);
660 if (delegation != NULL) { 670 if (delegation == NULL)
661 set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); 671 goto out;
662 nfs_mark_return_delegation(NFS_SERVER(inode), delegation); 672 if (stateid && !nfs4_stateid_match(stateid, &delegation->stateid))
663 } 673 goto out;
674 nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
675 ret = true;
676out:
664 rcu_read_unlock(); 677 rcu_read_unlock();
678 return ret;
665} 679}
666 680
667void nfs_remove_bad_delegation(struct inode *inode) 681void nfs_remove_bad_delegation(struct inode *inode,
682 const nfs4_stateid *stateid)
668{ 683{
669 struct nfs_delegation *delegation; 684 struct nfs_delegation *delegation;
670 685
671 nfs_revoke_delegation(inode); 686 if (!nfs_revoke_delegation(inode, stateid))
687 return;
672 delegation = nfs_inode_detach_delegation(inode); 688 delegation = nfs_inode_detach_delegation(inode);
673 if (delegation) { 689 if (delegation) {
674 nfs_inode_find_state_and_recover(inode, &delegation->stateid); 690 nfs_inode_find_state_and_recover(inode, &delegation->stateid);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 64724d252a79..d40827af5913 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -47,7 +47,7 @@ void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags);
47void nfs_expire_unreferenced_delegations(struct nfs_client *clp); 47void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
48int nfs_client_return_marked_delegations(struct nfs_client *clp); 48int nfs_client_return_marked_delegations(struct nfs_client *clp);
49int nfs_delegations_present(struct nfs_client *clp); 49int nfs_delegations_present(struct nfs_client *clp);
50void nfs_remove_bad_delegation(struct inode *inode); 50void nfs_remove_bad_delegation(struct inode *inode, const nfs4_stateid *stateid);
51 51
52void nfs_delegation_mark_reclaim(struct nfs_client *clp); 52void nfs_delegation_mark_reclaim(struct nfs_client *clp);
53void nfs_delegation_reap_unclaimed(struct nfs_client *clp); 53void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 51b51369704c..98ace127bf86 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1080,7 +1080,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
1080 case -NFS4ERR_BAD_STATEID: 1080 case -NFS4ERR_BAD_STATEID:
1081 if (state == NULL) 1081 if (state == NULL)
1082 break; 1082 break;
1083 nfs_remove_bad_delegation(state->inode); 1083 nfs_remove_bad_delegation(state->inode, NULL);
1084 case -NFS4ERR_OPENMODE: 1084 case -NFS4ERR_OPENMODE:
1085 if (state == NULL) 1085 if (state == NULL)
1086 break; 1086 break;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 04baee4327b2..4cc86001220a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2385,9 +2385,10 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
2385 return ret; 2385 return ret;
2386} 2386}
2387 2387
2388static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) 2388static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state,
2389 const nfs4_stateid *stateid)
2389{ 2390{
2390 nfs_remove_bad_delegation(state->inode); 2391 nfs_remove_bad_delegation(state->inode, stateid);
2391 write_seqlock(&state->seqlock); 2392 write_seqlock(&state->seqlock);
2392 nfs4_stateid_copy(&state->stateid, &state->open_stateid); 2393 nfs4_stateid_copy(&state->stateid, &state->open_stateid);
2393 write_sequnlock(&state->seqlock); 2394 write_sequnlock(&state->seqlock);
@@ -2397,7 +2398,7 @@ static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state)
2397static void nfs40_clear_delegation_stateid(struct nfs4_state *state) 2398static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
2398{ 2399{
2399 if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) 2400 if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
2400 nfs_finish_clear_delegation_stateid(state); 2401 nfs_finish_clear_delegation_stateid(state, NULL);
2401} 2402}
2402 2403
2403static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) 2404static 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 rcu_read_unlock(); 2444 rcu_read_unlock();
2444 return; 2445 return;
2445 } 2446 }
2447
2448 nfs4_stateid_copy(&stateid, &delegation->stateid);
2446 if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) { 2449 if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
2447 rcu_read_unlock(); 2450 rcu_read_unlock();
2448 nfs_finish_clear_delegation_stateid(state); 2451 nfs_finish_clear_delegation_stateid(state, &stateid);
2449 return; 2452 return;
2450 } 2453 }
2451 2454
2452 nfs4_stateid_copy(&stateid, &delegation->stateid);
2453 cred = get_rpccred(delegation->cred); 2455 cred = get_rpccred(delegation->cred);
2454 rcu_read_unlock(); 2456 rcu_read_unlock();
2455 status = nfs41_test_and_free_expired_stateid(server, &stateid, cred); 2457 status = nfs41_test_and_free_expired_stateid(server, &stateid, cred);
2456 trace_nfs4_test_delegation_stateid(state, NULL, status); 2458 trace_nfs4_test_delegation_stateid(state, NULL, status);
2457 if (status != NFS_OK) 2459 if (status != NFS_OK)
2458 nfs_finish_clear_delegation_stateid(state); 2460 nfs_finish_clear_delegation_stateid(state, &stateid);
2459 2461
2460 put_rpccred(cred); 2462 put_rpccred(cred);
2461} 2463}