|
|
@@ -3480,12 +3480,17 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
|
|
|
}
|
|
|
|
|
|
static struct nfs4_ol_stateid *
|
|
|
-init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
|
|
|
- struct nfsd4_open *open)
|
|
|
+init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
|
|
|
{
|
|
|
|
|
|
struct nfs4_openowner *oo = open->op_openowner;
|
|
|
struct nfs4_ol_stateid *retstp = NULL;
|
|
|
+ struct nfs4_ol_stateid *stp;
|
|
|
+
|
|
|
+ stp = open->op_stp;
|
|
|
+ /* We are moving these outside of the spinlocks to avoid the warnings */
|
|
|
+ mutex_init(&stp->st_mutex);
|
|
|
+ mutex_lock(&stp->st_mutex);
|
|
|
|
|
|
spin_lock(&oo->oo_owner.so_client->cl_lock);
|
|
|
spin_lock(&fp->fi_lock);
|
|
|
@@ -3493,6 +3498,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
|
|
|
retstp = nfsd4_find_existing_open(fp, open);
|
|
|
if (retstp)
|
|
|
goto out_unlock;
|
|
|
+
|
|
|
+ open->op_stp = NULL;
|
|
|
atomic_inc(&stp->st_stid.sc_count);
|
|
|
stp->st_stid.sc_type = NFS4_OPEN_STID;
|
|
|
INIT_LIST_HEAD(&stp->st_locks);
|
|
|
@@ -3502,14 +3509,19 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
|
|
|
stp->st_access_bmap = 0;
|
|
|
stp->st_deny_bmap = 0;
|
|
|
stp->st_openstp = NULL;
|
|
|
- init_rwsem(&stp->st_rwsem);
|
|
|
list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
|
|
|
list_add(&stp->st_perfile, &fp->fi_stateids);
|
|
|
|
|
|
out_unlock:
|
|
|
spin_unlock(&fp->fi_lock);
|
|
|
spin_unlock(&oo->oo_owner.so_client->cl_lock);
|
|
|
- return retstp;
|
|
|
+ if (retstp) {
|
|
|
+ mutex_lock(&retstp->st_mutex);
|
|
|
+ /* To keep mutex tracking happy */
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
+ stp = retstp;
|
|
|
+ }
|
|
|
+ return stp;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -4305,7 +4317,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
|
|
struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
|
|
|
struct nfs4_file *fp = NULL;
|
|
|
struct nfs4_ol_stateid *stp = NULL;
|
|
|
- struct nfs4_ol_stateid *swapstp = NULL;
|
|
|
struct nfs4_delegation *dp = NULL;
|
|
|
__be32 status;
|
|
|
|
|
|
@@ -4335,32 +4346,28 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
|
|
*/
|
|
|
if (stp) {
|
|
|
/* Stateid was found, this is an OPEN upgrade */
|
|
|
- down_read(&stp->st_rwsem);
|
|
|
+ mutex_lock(&stp->st_mutex);
|
|
|
status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
|
|
|
if (status) {
|
|
|
- up_read(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
goto out;
|
|
|
}
|
|
|
} else {
|
|
|
- stp = open->op_stp;
|
|
|
- open->op_stp = NULL;
|
|
|
- swapstp = init_open_stateid(stp, fp, open);
|
|
|
- if (swapstp) {
|
|
|
- nfs4_put_stid(&stp->st_stid);
|
|
|
- stp = swapstp;
|
|
|
- down_read(&stp->st_rwsem);
|
|
|
+ /* stp is returned locked. */
|
|
|
+ stp = init_open_stateid(fp, open);
|
|
|
+ /* See if we lost the race to some other thread */
|
|
|
+ if (stp->st_access_bmap != 0) {
|
|
|
status = nfs4_upgrade_open(rqstp, fp, current_fh,
|
|
|
stp, open);
|
|
|
if (status) {
|
|
|
- up_read(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
goto out;
|
|
|
}
|
|
|
goto upgrade_out;
|
|
|
}
|
|
|
- down_read(&stp->st_rwsem);
|
|
|
status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
|
|
|
if (status) {
|
|
|
- up_read(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
release_open_stateid(stp);
|
|
|
goto out;
|
|
|
}
|
|
|
@@ -4372,7 +4379,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
|
|
}
|
|
|
upgrade_out:
|
|
|
nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
|
|
|
- up_read(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
|
|
|
if (nfsd4_has_session(&resp->cstate)) {
|
|
|
if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
|
|
|
@@ -4977,12 +4984,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
|
|
|
* revoked delegations are kept only for free_stateid.
|
|
|
*/
|
|
|
return nfserr_bad_stateid;
|
|
|
- down_write(&stp->st_rwsem);
|
|
|
+ mutex_lock(&stp->st_mutex);
|
|
|
status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
|
|
|
if (status == nfs_ok)
|
|
|
status = nfs4_check_fh(current_fh, &stp->st_stid);
|
|
|
if (status != nfs_ok)
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
@@ -5030,7 +5037,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs
|
|
|
return status;
|
|
|
oo = openowner(stp->st_stateowner);
|
|
|
if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
nfs4_put_stid(&stp->st_stid);
|
|
|
return nfserr_bad_stateid;
|
|
|
}
|
|
|
@@ -5062,12 +5069,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
oo = openowner(stp->st_stateowner);
|
|
|
status = nfserr_bad_stateid;
|
|
|
if (oo->oo_flags & NFS4_OO_CONFIRMED) {
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
goto put_stateid;
|
|
|
}
|
|
|
oo->oo_flags |= NFS4_OO_CONFIRMED;
|
|
|
nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
|
|
|
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
|
|
|
|
|
|
@@ -5143,7 +5150,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
|
|
|
nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
|
|
|
status = nfs_ok;
|
|
|
put_stateid:
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
nfs4_put_stid(&stp->st_stid);
|
|
|
out:
|
|
|
nfsd4_bump_seqid(cstate, status);
|
|
|
@@ -5196,7 +5203,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
if (status)
|
|
|
goto out;
|
|
|
nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
|
|
|
nfsd4_close_open_stateid(stp);
|
|
|
|
|
|
@@ -5422,7 +5429,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
|
|
|
stp->st_access_bmap = 0;
|
|
|
stp->st_deny_bmap = open_stp->st_deny_bmap;
|
|
|
stp->st_openstp = open_stp;
|
|
|
- init_rwsem(&stp->st_rwsem);
|
|
|
+ mutex_init(&stp->st_mutex);
|
|
|
list_add(&stp->st_locks, &open_stp->st_locks);
|
|
|
list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
|
|
|
spin_lock(&fp->fi_lock);
|
|
|
@@ -5591,7 +5598,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
&open_stp, nn);
|
|
|
if (status)
|
|
|
goto out;
|
|
|
- up_write(&open_stp->st_rwsem);
|
|
|
+ mutex_unlock(&open_stp->st_mutex);
|
|
|
open_sop = openowner(open_stp->st_stateowner);
|
|
|
status = nfserr_bad_stateid;
|
|
|
if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
|
|
|
@@ -5600,7 +5607,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
status = lookup_or_create_lock_state(cstate, open_stp, lock,
|
|
|
&lock_stp, &new);
|
|
|
if (status == nfs_ok)
|
|
|
- down_write(&lock_stp->st_rwsem);
|
|
|
+ mutex_lock(&lock_stp->st_mutex);
|
|
|
} else {
|
|
|
status = nfs4_preprocess_seqid_op(cstate,
|
|
|
lock->lk_old_lock_seqid,
|
|
|
@@ -5704,7 +5711,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
seqid_mutating_err(ntohl(status)))
|
|
|
lock_sop->lo_owner.so_seqid++;
|
|
|
|
|
|
- up_write(&lock_stp->st_rwsem);
|
|
|
+ mutex_unlock(&lock_stp->st_mutex);
|
|
|
|
|
|
/*
|
|
|
* If this is a new, never-before-used stateid, and we are
|
|
|
@@ -5874,7 +5881,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
fput:
|
|
|
fput(filp);
|
|
|
put_stateid:
|
|
|
- up_write(&stp->st_rwsem);
|
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
|
nfs4_put_stid(&stp->st_stid);
|
|
|
out:
|
|
|
nfsd4_bump_seqid(cstate, status);
|