Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Trond Myklebust and committed by
Anna Schumaker
41020b67 4586f6e2

+37 -19
+27 -11
fs/nfs/delegation.c
··· 652 652 rcu_read_unlock(); 653 653 } 654 654 655 - static void nfs_revoke_delegation(struct inode *inode) 655 + static void nfs_mark_delegation_revoked(struct nfs_server *server, 656 + struct nfs_delegation *delegation) 656 657 { 657 - struct nfs_delegation *delegation; 658 - rcu_read_lock(); 659 - delegation = rcu_dereference(NFS_I(inode)->delegation); 660 - if (delegation != NULL) { 661 - set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); 662 - nfs_mark_return_delegation(NFS_SERVER(inode), delegation); 663 - } 664 - rcu_read_unlock(); 658 + set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); 659 + nfs_mark_return_delegation(server, delegation); 665 660 } 666 661 667 - void nfs_remove_bad_delegation(struct inode *inode) 662 + static bool nfs_revoke_delegation(struct inode *inode, 663 + const nfs4_stateid *stateid) 664 + { 665 + struct nfs_delegation *delegation; 666 + bool ret = false; 667 + 668 + rcu_read_lock(); 669 + delegation = rcu_dereference(NFS_I(inode)->delegation); 670 + if (delegation == NULL) 671 + goto out; 672 + if (stateid && !nfs4_stateid_match(stateid, &delegation->stateid)) 673 + goto out; 674 + nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation); 675 + ret = true; 676 + out: 677 + rcu_read_unlock(); 678 + return ret; 679 + } 680 + 681 + void nfs_remove_bad_delegation(struct inode *inode, 682 + const nfs4_stateid *stateid) 668 683 { 669 684 struct nfs_delegation *delegation; 670 685 671 - nfs_revoke_delegation(inode); 686 + if (!nfs_revoke_delegation(inode, stateid)) 687 + return; 672 688 delegation = nfs_inode_detach_delegation(inode); 673 689 if (delegation) { 674 690 nfs_inode_find_state_and_recover(inode, &delegation->stateid);
+1 -1
fs/nfs/delegation.h
··· 47 47 void nfs_expire_unreferenced_delegations(struct nfs_client *clp); 48 48 int nfs_client_return_marked_delegations(struct nfs_client *clp); 49 49 int nfs_delegations_present(struct nfs_client *clp); 50 - void nfs_remove_bad_delegation(struct inode *inode); 50 + void nfs_remove_bad_delegation(struct inode *inode, const nfs4_stateid *stateid); 51 51 52 52 void nfs_delegation_mark_reclaim(struct nfs_client *clp); 53 53 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
+1 -1
fs/nfs/flexfilelayout/flexfilelayout.c
··· 1080 1080 case -NFS4ERR_BAD_STATEID: 1081 1081 if (state == NULL) 1082 1082 break; 1083 - nfs_remove_bad_delegation(state->inode); 1083 + nfs_remove_bad_delegation(state->inode, NULL); 1084 1084 case -NFS4ERR_OPENMODE: 1085 1085 if (state == NULL) 1086 1086 break;
+8 -6
fs/nfs/nfs4proc.c
··· 2385 2385 return ret; 2386 2386 } 2387 2387 2388 - static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) 2388 + static 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 2392 write_seqlock(&state->seqlock); 2392 2393 nfs4_stateid_copy(&state->stateid, &state->open_stateid); 2393 2394 write_sequnlock(&state->seqlock); ··· 2398 2397 static void nfs40_clear_delegation_stateid(struct nfs4_state *state) 2399 2398 { 2400 2399 if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) 2401 - nfs_finish_clear_delegation_stateid(state); 2400 + nfs_finish_clear_delegation_stateid(state, NULL); 2402 2401 } 2403 2402 2404 2403 static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) ··· 2444 2443 rcu_read_unlock(); 2445 2444 return; 2446 2445 } 2446 + 2447 + nfs4_stateid_copy(&stateid, &delegation->stateid); 2447 2448 if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) { 2448 2449 rcu_read_unlock(); 2449 - nfs_finish_clear_delegation_stateid(state); 2450 + nfs_finish_clear_delegation_stateid(state, &stateid); 2450 2451 return; 2451 2452 } 2452 2453 2453 - nfs4_stateid_copy(&stateid, &delegation->stateid); 2454 2454 cred = get_rpccred(delegation->cred); 2455 2455 rcu_read_unlock(); 2456 2456 status = nfs41_test_and_free_expired_stateid(server, &stateid, cred); 2457 2457 trace_nfs4_test_delegation_stateid(state, NULL, status); 2458 2458 if (status != NFS_OK) 2459 - nfs_finish_clear_delegation_stateid(state); 2459 + nfs_finish_clear_delegation_stateid(state, &stateid); 2460 2460 2461 2461 put_rpccred(cred); 2462 2462 }