diff options
Diffstat (limited to 'fs/nfs/delegation.c')
| -rw-r--r-- | fs/nfs/delegation.c | 25 | 
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:  			continue;  		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))  			continue; +		if (!nfs4_valid_open_stateid(state)) +			continue;  		if (!nfs4_stateid_match(&state->stateid, stateid))  			continue;  		get_nfs_open_context(ctx); @@ -193,7 +195,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *  {  	int res = 0; -	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); +	if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) +		res = nfs4_proc_delegreturn(inode, +				delegation->cred, +				&delegation->stateid, +				issync);  	nfs_free_delegation(delegation);  	return res;  } @@ -380,11 +386,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation  {  	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;  	struct nfs_inode *nfsi = NFS_I(inode); -	int err; +	int err = 0;  	if (delegation == NULL)  		return 0;  	do { +		if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) +			break;  		err = nfs_delegation_claim_opens(inode, &delegation->stateid);  		if (!issync || err != -EAGAIN)  			break; @@ -605,10 +613,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl  	rcu_read_unlock();  } +static void nfs_revoke_delegation(struct inode *inode) +{ +	struct nfs_delegation *delegation; +	rcu_read_lock(); +	delegation = rcu_dereference(NFS_I(inode)->delegation); +	if (delegation != NULL) { +		set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); +		nfs_mark_return_delegation(NFS_SERVER(inode), delegation); +	} +	rcu_read_unlock(); +} +  void nfs_remove_bad_delegation(struct inode *inode)  {  	struct nfs_delegation *delegation; +	nfs_revoke_delegation(inode);  	delegation = nfs_inode_detach_delegation(inode);  	if (delegation) {  		nfs_inode_find_state_and_recover(inode, &delegation->stateid);  | 
