diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/nfsd/nfs4state.c | 19 | 
1 files changed, 8 insertions, 11 deletions
| diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index afc04b9784a0..6542b57ecc86 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -5149,7 +5149,9 @@ nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)  	struct nfs4_ol_stateid *stp = openlockstateid(s);  	__be32 ret; -	mutex_lock(&stp->st_mutex); +	ret = nfsd4_lock_ol_stateid(stp); +	if (ret) +		goto out_put_stid;  	ret = check_stateid_generation(stateid, &s->sc_stateid, 1);  	if (ret) @@ -5160,11 +5162,13 @@ nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)  			    lockowner(stp->st_stateowner)))  		goto out; +	stp->st_stid.sc_type = NFS4_CLOSED_STID;  	release_lock_stateid(stp);  	ret = nfs_ok;  out:  	mutex_unlock(&stp->st_mutex); +out_put_stid:  	nfs4_put_stid(s);  	return ret;  } @@ -5733,6 +5737,8 @@ find_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp)  	lockdep_assert_held(&clp->cl_lock);  	list_for_each_entry(lst, &lo->lo_owner.so_stateids, st_perstateowner) { +		if (lst->st_stid.sc_type != NFS4_LOCK_STID) +			continue;  		if (lst->st_stid.sc_file == fp) {  			refcount_inc(&lst->st_stid.sc_count);  			return lst; @@ -5807,7 +5813,6 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,  	struct nfs4_lockowner *lo;  	struct nfs4_ol_stateid *lst;  	unsigned int strhashval; -	bool hashed;  	lo = find_lockowner_str(cl, &lock->lk_new_owner);  	if (!lo) { @@ -5830,15 +5835,7 @@ retry:  		goto out;  	} -	mutex_lock(&lst->st_mutex); - -	/* See if it's still hashed to avoid race with FREE_STATEID */ -	spin_lock(&cl->cl_lock); -	hashed = !list_empty(&lst->st_perfile); -	spin_unlock(&cl->cl_lock); - -	if (!hashed) { -		mutex_unlock(&lst->st_mutex); +	if (nfsd4_lock_ol_stateid(lst) != nfs_ok) {  		nfs4_put_stid(&lst->st_stid);  		goto retry;  	} |