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.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index a1f0685b42ff..a6ad68865880 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -181,8 +181,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
181 clear_bit(NFS_DELEGATION_NEED_RECLAIM, 181 clear_bit(NFS_DELEGATION_NEED_RECLAIM,
182 &delegation->flags); 182 &delegation->flags);
183 spin_unlock(&delegation->lock); 183 spin_unlock(&delegation->lock);
184 put_rpccred(oldcred);
185 rcu_read_unlock(); 184 rcu_read_unlock();
185 put_rpccred(oldcred);
186 trace_nfs4_reclaim_delegation(inode, res->delegation_type); 186 trace_nfs4_reclaim_delegation(inode, res->delegation_type);
187 } else { 187 } else {
188 /* We appear to have raced with a delegation return. */ 188 /* We appear to have raced with a delegation return. */
@@ -370,7 +370,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
370 delegation = NULL; 370 delegation = NULL;
371 goto out; 371 goto out;
372 } 372 }
373 freeme = nfs_detach_delegation_locked(nfsi, 373 if (test_and_set_bit(NFS_DELEGATION_RETURNING,
374 &old_delegation->flags))
375 goto out;
376 freeme = nfs_detach_delegation_locked(nfsi,
374 old_delegation, clp); 377 old_delegation, clp);
375 if (freeme == NULL) 378 if (freeme == NULL)
376 goto out; 379 goto out;
@@ -433,6 +436,8 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
433{ 436{
434 bool ret = false; 437 bool ret = false;
435 438
439 if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
440 goto out;
436 if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) 441 if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
437 ret = true; 442 ret = true;
438 if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) { 443 if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) {
@@ -444,6 +449,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
444 ret = true; 449 ret = true;
445 spin_unlock(&delegation->lock); 450 spin_unlock(&delegation->lock);
446 } 451 }
452out:
447 return ret; 453 return ret;
448} 454}
449 455
@@ -471,14 +477,20 @@ restart:
471 super_list) { 477 super_list) {
472 if (!nfs_delegation_need_return(delegation)) 478 if (!nfs_delegation_need_return(delegation))
473 continue; 479 continue;
474 inode = nfs_delegation_grab_inode(delegation); 480 if (!nfs_sb_active(server->super))
475 if (inode == NULL)
476 continue; 481 continue;
482 inode = nfs_delegation_grab_inode(delegation);
483 if (inode == NULL) {
484 rcu_read_unlock();
485 nfs_sb_deactive(server->super);
486 goto restart;
487 }
477 delegation = nfs_start_delegation_return_locked(NFS_I(inode)); 488 delegation = nfs_start_delegation_return_locked(NFS_I(inode));
478 rcu_read_unlock(); 489 rcu_read_unlock();
479 490
480 err = nfs_end_delegation_return(inode, delegation, 0); 491 err = nfs_end_delegation_return(inode, delegation, 0);
481 iput(inode); 492 iput(inode);
493 nfs_sb_deactive(server->super);
482 if (!err) 494 if (!err)
483 goto restart; 495 goto restart;
484 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); 496 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
@@ -809,19 +821,30 @@ restart:
809 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { 821 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
810 list_for_each_entry_rcu(delegation, &server->delegations, 822 list_for_each_entry_rcu(delegation, &server->delegations,
811 super_list) { 823 super_list) {
824 if (test_bit(NFS_DELEGATION_RETURNING,
825 &delegation->flags))
826 continue;
812 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, 827 if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
813 &delegation->flags) == 0) 828 &delegation->flags) == 0)
814 continue; 829 continue;
815 inode = nfs_delegation_grab_inode(delegation); 830 if (!nfs_sb_active(server->super))
816 if (inode == NULL)
817 continue; 831 continue;
818 delegation = nfs_detach_delegation(NFS_I(inode), 832 inode = nfs_delegation_grab_inode(delegation);
819 delegation, server); 833 if (inode == NULL) {
834 rcu_read_unlock();
835 nfs_sb_deactive(server->super);
836 goto restart;
837 }
838 delegation = nfs_start_delegation_return_locked(NFS_I(inode));
820 rcu_read_unlock(); 839 rcu_read_unlock();
821 840 if (delegation != NULL) {
822 if (delegation != NULL) 841 delegation = nfs_detach_delegation(NFS_I(inode),
823 nfs_free_delegation(delegation); 842 delegation, server);
843 if (delegation != NULL)
844 nfs_free_delegation(delegation);
845 }
824 iput(inode); 846 iput(inode);
847 nfs_sb_deactive(server->super);
825 goto restart; 848 goto restart;
826 } 849 }
827 } 850 }