|
|
@@ -4903,6 +4903,32 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
return nfs_ok;
|
|
|
}
|
|
|
|
|
|
+static __be32
|
|
|
+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 = check_stateid_generation(stateid, &s->sc_stateid, 1);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret = nfserr_locks_held;
|
|
|
+ if (check_for_locks(stp->st_stid.sc_file,
|
|
|
+ lockowner(stp->st_stateowner)))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ release_lock_stateid(stp);
|
|
|
+ ret = nfs_ok;
|
|
|
+
|
|
|
+out:
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
+ nfs4_put_stid(s);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
__be32
|
|
|
nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
struct nfsd4_free_stateid *free_stateid)
|
|
|
@@ -4910,7 +4936,6 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
stateid_t *stateid = &free_stateid->fr_stateid;
|
|
|
struct nfs4_stid *s;
|
|
|
struct nfs4_delegation *dp;
|
|
|
- struct nfs4_ol_stateid *stp;
|
|
|
struct nfs4_client *cl = cstate->session->se_client;
|
|
|
__be32 ret = nfserr_bad_stateid;
|
|
|
|
|
|
@@ -4929,18 +4954,9 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
ret = nfserr_locks_held;
|
|
|
break;
|
|
|
case NFS4_LOCK_STID:
|
|
|
- ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
|
|
|
- if (ret)
|
|
|
- break;
|
|
|
- stp = openlockstateid(s);
|
|
|
- ret = nfserr_locks_held;
|
|
|
- if (check_for_locks(stp->st_stid.sc_file,
|
|
|
- lockowner(stp->st_stateowner)))
|
|
|
- break;
|
|
|
- WARN_ON(!unhash_lock_stateid(stp));
|
|
|
+ atomic_inc(&s->sc_count);
|
|
|
spin_unlock(&cl->cl_lock);
|
|
|
- nfs4_put_stid(s);
|
|
|
- ret = nfs_ok;
|
|
|
+ ret = nfsd4_free_lock_stateid(stateid, s);
|
|
|
goto out;
|
|
|
case NFS4_REVOKED_DELEG_STID:
|
|
|
dp = delegstateid(s);
|