diff options
-rw-r--r-- | fs/nfsd/nfs4state.c | 33 | ||||
-rw-r--r-- | fs/nfsd/state.h | 19 |
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; |
4984 | put_stateid: | 4998 | put_stateid: |
4999 | up_write(&stp->st_rwsem); | ||
4985 | nfs4_put_stid(&stp->st_stid); | 5000 | nfs4_put_stid(&stp->st_stid); |
4986 | out: | 5001 | out: |
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, | |||
5709 | fput: | 5731 | fput: |
5710 | fput(filp); | 5732 | fput(filp); |
5711 | put_stateid: | 5733 | put_stateid: |
5734 | up_write(&stp->st_rwsem); | ||
5712 | nfs4_put_stid(&stp->st_stid); | 5735 | nfs4_put_stid(&stp->st_stid); |
5713 | out: | 5736 | out: |
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 | */ |
536 | struct nfs4_ol_stateid { | 536 | struct 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 | ||
548 | static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) | 549 | static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) |