aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4state.c33
-rw-r--r--fs/nfsd/state.h19
2 files changed, 38 insertions, 14 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0f1d5691b795..1b39edf10b67 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3360,6 +3360,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
3360 stp->st_access_bmap = 0; 3360 stp->st_access_bmap = 0;
3361 stp->st_deny_bmap = 0; 3361 stp->st_deny_bmap = 0;
3362 stp->st_openstp = NULL; 3362 stp->st_openstp = NULL;
3363 init_rwsem(&stp->st_rwsem);
3363 spin_lock(&oo->oo_owner.so_client->cl_lock); 3364 spin_lock(&oo->oo_owner.so_client->cl_lock);
3364 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); 3365 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
3365 spin_lock(&fp->fi_lock); 3366 spin_lock(&fp->fi_lock);
@@ -4187,15 +4188,20 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
4187 */ 4188 */
4188 if (stp) { 4189 if (stp) {
4189 /* Stateid was found, this is an OPEN upgrade */ 4190 /* Stateid was found, this is an OPEN upgrade */
4191 down_read(&stp->st_rwsem);
4190 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); 4192 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
4191 if (status) 4193 if (status) {
4194 up_read(&stp->st_rwsem);
4192 goto out; 4195 goto out;
4196 }
4193 } else { 4197 } else {
4194 stp = open->op_stp; 4198 stp = open->op_stp;
4195 open->op_stp = NULL; 4199 open->op_stp = NULL;
4196 init_open_stateid(stp, fp, open); 4200 init_open_stateid(stp, fp, open);
4201 down_read(&stp->st_rwsem);
4197 status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); 4202 status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
4198 if (status) { 4203 if (status) {
4204 up_read(&stp->st_rwsem);
4199 release_open_stateid(stp); 4205 release_open_stateid(stp);
4200 goto out; 4206 goto out;
4201 } 4207 }
@@ -4207,6 +4213,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
4207 } 4213 }
4208 update_stateid(&stp->st_stid.sc_stateid); 4214 update_stateid(&stp->st_stid.sc_stateid);
4209 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4215 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4216 up_read(&stp->st_rwsem);
4210 4217
4211 if (nfsd4_has_session(&resp->cstate)) { 4218 if (nfsd4_has_session(&resp->cstate)) {
4212 if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { 4219 if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
@@ -4819,10 +4826,13 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
4819 * revoked delegations are kept only for free_stateid. 4826 * revoked delegations are kept only for free_stateid.
4820 */ 4827 */
4821 return nfserr_bad_stateid; 4828 return nfserr_bad_stateid;
4829 down_write(&stp->st_rwsem);
4822 status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); 4830 status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
4823 if (status) 4831 if (status == nfs_ok)
4824 return status; 4832 status = nfs4_check_fh(current_fh, &stp->st_stid);
4825 return nfs4_check_fh(current_fh, &stp->st_stid); 4833 if (status != nfs_ok)
4834 up_write(&stp->st_rwsem);
4835 return status;
4826} 4836}
4827 4837
4828/* 4838/*
@@ -4869,6 +4879,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs
4869 return status; 4879 return status;
4870 oo = openowner(stp->st_stateowner); 4880 oo = openowner(stp->st_stateowner);
4871 if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { 4881 if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
4882 up_write(&stp->st_rwsem);
4872 nfs4_put_stid(&stp->st_stid); 4883 nfs4_put_stid(&stp->st_stid);
4873 return nfserr_bad_stateid; 4884 return nfserr_bad_stateid;
4874 } 4885 }
@@ -4899,11 +4910,14 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4899 goto out; 4910 goto out;
4900 oo = openowner(stp->st_stateowner); 4911 oo = openowner(stp->st_stateowner);
4901 status = nfserr_bad_stateid; 4912 status = nfserr_bad_stateid;
4902 if (oo->oo_flags & NFS4_OO_CONFIRMED) 4913 if (oo->oo_flags & NFS4_OO_CONFIRMED) {
4914 up_write(&stp->st_rwsem);
4903 goto put_stateid; 4915 goto put_stateid;
4916 }
4904 oo->oo_flags |= NFS4_OO_CONFIRMED; 4917 oo->oo_flags |= NFS4_OO_CONFIRMED;
4905 update_stateid(&stp->st_stid.sc_stateid); 4918 update_stateid(&stp->st_stid.sc_stateid);
4906 memcpy(&oc->oc_resp_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4919 memcpy(&oc->oc_resp_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4920 up_write(&stp->st_rwsem);
4907 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", 4921 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
4908 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); 4922 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
4909 4923
@@ -4982,6 +4996,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
4982 memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4996 memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4983 status = nfs_ok; 4997 status = nfs_ok;
4984put_stateid: 4998put_stateid:
4999 up_write(&stp->st_rwsem);
4985 nfs4_put_stid(&stp->st_stid); 5000 nfs4_put_stid(&stp->st_stid);
4986out: 5001out:
4987 nfsd4_bump_seqid(cstate, status); 5002 nfsd4_bump_seqid(cstate, status);
@@ -5035,6 +5050,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5035 goto out; 5050 goto out;
5036 update_stateid(&stp->st_stid.sc_stateid); 5051 update_stateid(&stp->st_stid.sc_stateid);
5037 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 5052 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
5053 up_write(&stp->st_rwsem);
5038 5054
5039 nfsd4_close_open_stateid(stp); 5055 nfsd4_close_open_stateid(stp);
5040 5056
@@ -5260,6 +5276,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
5260 stp->st_access_bmap = 0; 5276 stp->st_access_bmap = 0;
5261 stp->st_deny_bmap = open_stp->st_deny_bmap; 5277 stp->st_deny_bmap = open_stp->st_deny_bmap;
5262 stp->st_openstp = open_stp; 5278 stp->st_openstp = open_stp;
5279 init_rwsem(&stp->st_rwsem);
5263 list_add(&stp->st_locks, &open_stp->st_locks); 5280 list_add(&stp->st_locks, &open_stp->st_locks);
5264 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); 5281 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
5265 spin_lock(&fp->fi_lock); 5282 spin_lock(&fp->fi_lock);
@@ -5428,6 +5445,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5428 &open_stp, nn); 5445 &open_stp, nn);
5429 if (status) 5446 if (status)
5430 goto out; 5447 goto out;
5448 up_write(&open_stp->st_rwsem);
5431 open_sop = openowner(open_stp->st_stateowner); 5449 open_sop = openowner(open_stp->st_stateowner);
5432 status = nfserr_bad_stateid; 5450 status = nfserr_bad_stateid;
5433 if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, 5451 if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
@@ -5435,6 +5453,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5435 goto out; 5453 goto out;
5436 status = lookup_or_create_lock_state(cstate, open_stp, lock, 5454 status = lookup_or_create_lock_state(cstate, open_stp, lock,
5437 &lock_stp, &new); 5455 &lock_stp, &new);
5456 if (status == nfs_ok)
5457 down_write(&lock_stp->st_rwsem);
5438 } else { 5458 } else {
5439 status = nfs4_preprocess_seqid_op(cstate, 5459 status = nfs4_preprocess_seqid_op(cstate,
5440 lock->lk_old_lock_seqid, 5460 lock->lk_old_lock_seqid,
@@ -5540,6 +5560,8 @@ out:
5540 seqid_mutating_err(ntohl(status))) 5560 seqid_mutating_err(ntohl(status)))
5541 lock_sop->lo_owner.so_seqid++; 5561 lock_sop->lo_owner.so_seqid++;
5542 5562
5563 up_write(&lock_stp->st_rwsem);
5564
5543 /* 5565 /*
5544 * If this is a new, never-before-used stateid, and we are 5566 * If this is a new, never-before-used stateid, and we are
5545 * returning an error, then just go ahead and release it. 5567 * returning an error, then just go ahead and release it.
@@ -5709,6 +5731,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5709fput: 5731fput:
5710 fput(filp); 5732 fput(filp);
5711put_stateid: 5733put_stateid:
5734 up_write(&stp->st_rwsem);
5712 nfs4_put_stid(&stp->st_stid); 5735 nfs4_put_stid(&stp->st_stid);
5713out: 5736out:
5714 nfsd4_bump_seqid(cstate, status); 5737 nfsd4_bump_seqid(cstate, status);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 583ffc13cae2..31bde12feefe 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -534,15 +534,16 @@ struct nfs4_file {
534 * Better suggestions welcome. 534 * Better suggestions welcome.
535 */ 535 */
536struct nfs4_ol_stateid { 536struct nfs4_ol_stateid {
537 struct nfs4_stid st_stid; /* must be first field */ 537 struct nfs4_stid st_stid;
538 struct list_head st_perfile; 538 struct list_head st_perfile;
539 struct list_head st_perstateowner; 539 struct list_head st_perstateowner;
540 struct list_head st_locks; 540 struct list_head st_locks;
541 struct nfs4_stateowner * st_stateowner; 541 struct nfs4_stateowner *st_stateowner;
542 struct nfs4_clnt_odstate * st_clnt_odstate; 542 struct nfs4_clnt_odstate *st_clnt_odstate;
543 unsigned char st_access_bmap; 543 unsigned char st_access_bmap;
544 unsigned char st_deny_bmap; 544 unsigned char st_deny_bmap;
545 struct nfs4_ol_stateid * st_openstp; 545 struct nfs4_ol_stateid *st_openstp;
546 struct rw_semaphore st_rwsem;
546}; 547};
547 548
548static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) 549static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)