summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c12
-rw-r--r--fs/nfsd/nfs4state.c47
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/state.h1
-rw-r--r--fs/nfsd/xdr4.h5
5 files changed, 41 insertions, 26 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 8611585f739d..29cf395b694e 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -469,12 +469,9 @@ out:
469 fh_put(resfh); 469 fh_put(resfh);
470 kfree(resfh); 470 kfree(resfh);
471 } 471 }
472 nfsd4_cleanup_open_state(open, status); 472 nfsd4_cleanup_open_state(cstate, open, status);
473 if (open->op_openowner && !nfsd4_has_session(cstate))
474 cstate->replay_owner = &open->op_openowner->oo_owner;
475 nfsd4_bump_seqid(cstate, status); 473 nfsd4_bump_seqid(cstate, status);
476 if (!cstate->replay_owner) 474 nfs4_unlock_state();
477 nfs4_unlock_state();
478 return status; 475 return status;
479} 476}
480 477
@@ -1395,10 +1392,7 @@ encode_op:
1395 args->ops, args->opcnt, resp->opcnt, op->opnum, 1392 args->ops, args->opcnt, resp->opcnt, op->opnum,
1396 be32_to_cpu(status)); 1393 be32_to_cpu(status));
1397 1394
1398 if (cstate->replay_owner) { 1395 nfsd4_cstate_clear_replay(cstate);
1399 nfs4_unlock_state();
1400 cstate->replay_owner = NULL;
1401 }
1402 /* XXX Ugh, we need to get rid of this kind of special case: */ 1396 /* XXX Ugh, we need to get rid of this kind of special case: */
1403 if (op->opnum == OP_READ && op->u.read.rd_filp) 1397 if (op->opnum == OP_READ && op->u.read.rd_filp)
1404 fput(op->u.read.rd_filp); 1398 fput(op->u.read.rd_filp);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5a93e5fafd4a..749608b914b4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1069,7 +1069,7 @@ void nfsd4_bump_seqid(struct nfsd4_compound_state *cstate, __be32 nfserr)
1069 return; 1069 return;
1070 1070
1071 if (!seqid_mutating_err(ntohl(nfserr))) { 1071 if (!seqid_mutating_err(ntohl(nfserr))) {
1072 cstate->replay_owner = NULL; 1072 nfsd4_cstate_clear_replay(cstate);
1073 return; 1073 return;
1074 } 1074 }
1075 if (!so) 1075 if (!so)
@@ -2940,6 +2940,28 @@ static void init_nfs4_replay(struct nfs4_replay *rp)
2940 rp->rp_status = nfserr_serverfault; 2940 rp->rp_status = nfserr_serverfault;
2941 rp->rp_buflen = 0; 2941 rp->rp_buflen = 0;
2942 rp->rp_buf = rp->rp_ibuf; 2942 rp->rp_buf = rp->rp_ibuf;
2943 mutex_init(&rp->rp_mutex);
2944}
2945
2946static void nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate,
2947 struct nfs4_stateowner *so)
2948{
2949 if (!nfsd4_has_session(cstate)) {
2950 mutex_lock(&so->so_replay.rp_mutex);
2951 cstate->replay_owner = so;
2952 atomic_inc(&so->so_count);
2953 }
2954}
2955
2956void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate)
2957{
2958 struct nfs4_stateowner *so = cstate->replay_owner;
2959
2960 if (so != NULL) {
2961 cstate->replay_owner = NULL;
2962 mutex_unlock(&so->so_replay.rp_mutex);
2963 nfs4_put_stateowner(so);
2964 }
2943} 2965}
2944 2966
2945static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj *owner, struct nfs4_client *clp) 2967static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj *owner, struct nfs4_client *clp)
@@ -3855,7 +3877,8 @@ out:
3855 return status; 3877 return status;
3856} 3878}
3857 3879
3858void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status) 3880void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
3881 struct nfsd4_open *open, __be32 status)
3859{ 3882{
3860 if (open->op_openowner) { 3883 if (open->op_openowner) {
3861 struct nfs4_openowner *oo = open->op_openowner; 3884 struct nfs4_openowner *oo = open->op_openowner;
@@ -3869,6 +3892,8 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
3869 } else 3892 } else
3870 oo->oo_flags &= ~NFS4_OO_NEW; 3893 oo->oo_flags &= ~NFS4_OO_NEW;
3871 } 3894 }
3895 if (open->op_openowner)
3896 nfsd4_cstate_assign_replay(cstate, &oo->oo_owner);
3872 } 3897 }
3873 if (open->op_file) 3898 if (open->op_file)
3874 nfsd4_free_file(open->op_file); 3899 nfsd4_free_file(open->op_file);
@@ -4399,8 +4424,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
4399 if (status) 4424 if (status)
4400 return status; 4425 return status;
4401 stp = openlockstateid(s); 4426 stp = openlockstateid(s);
4402 if (!nfsd4_has_session(cstate)) 4427 nfsd4_cstate_assign_replay(cstate, stp->st_stateowner);
4403 cstate->replay_owner = stp->st_stateowner;
4404 4428
4405 status = nfs4_seqid_op_checks(cstate, stateid, seqid, stp); 4429 status = nfs4_seqid_op_checks(cstate, stateid, seqid, stp);
4406 if (!status) 4430 if (!status)
@@ -4469,8 +4493,7 @@ put_stateid:
4469 nfs4_put_stid(&stp->st_stid); 4493 nfs4_put_stid(&stp->st_stid);
4470out: 4494out:
4471 nfsd4_bump_seqid(cstate, status); 4495 nfsd4_bump_seqid(cstate, status);
4472 if (!cstate->replay_owner) 4496 nfs4_unlock_state();
4473 nfs4_unlock_state();
4474 return status; 4497 return status;
4475} 4498}
4476 4499
@@ -4544,8 +4567,7 @@ put_stateid:
4544 nfs4_put_stid(&stp->st_stid); 4567 nfs4_put_stid(&stp->st_stid);
4545out: 4568out:
4546 nfsd4_bump_seqid(cstate, status); 4569 nfsd4_bump_seqid(cstate, status);
4547 if (!cstate->replay_owner) 4570 nfs4_unlock_state();
4548 nfs4_unlock_state();
4549 return status; 4571 return status;
4550} 4572}
4551 4573
@@ -4610,8 +4632,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4610 /* put reference from nfs4_preprocess_seqid_op */ 4632 /* put reference from nfs4_preprocess_seqid_op */
4611 nfs4_put_stid(&stp->st_stid); 4633 nfs4_put_stid(&stp->st_stid);
4612out: 4634out:
4613 if (!cstate->replay_owner) 4635 nfs4_unlock_state();
4614 nfs4_unlock_state();
4615 return status; 4636 return status;
4616} 4637}
4617 4638
@@ -5071,8 +5092,7 @@ out:
5071 if (status && new_state) 5092 if (status && new_state)
5072 release_lock_stateid(lock_stp); 5093 release_lock_stateid(lock_stp);
5073 nfsd4_bump_seqid(cstate, status); 5094 nfsd4_bump_seqid(cstate, status);
5074 if (!cstate->replay_owner) 5095 nfs4_unlock_state();
5075 nfs4_unlock_state();
5076 if (file_lock) 5096 if (file_lock)
5077 locks_free_lock(file_lock); 5097 locks_free_lock(file_lock);
5078 if (conflock) 5098 if (conflock)
@@ -5236,8 +5256,7 @@ put_stateid:
5236 nfs4_put_stid(&stp->st_stid); 5256 nfs4_put_stid(&stp->st_stid);
5237out: 5257out:
5238 nfsd4_bump_seqid(cstate, status); 5258 nfsd4_bump_seqid(cstate, status);
5239 if (!cstate->replay_owner) 5259 nfs4_unlock_state();
5240 nfs4_unlock_state();
5241 if (file_lock) 5260 if (file_lock)
5242 locks_free_lock(file_lock); 5261 locks_free_lock(file_lock);
5243 return status; 5262 return status;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 628b430e743e..72a2a82e11a4 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3925,8 +3925,6 @@ status:
3925 * 3925 *
3926 * XDR note: do not encode rp->rp_buflen: the buffer contains the 3926 * XDR note: do not encode rp->rp_buflen: the buffer contains the
3927 * previously sent already encoded operation. 3927 * previously sent already encoded operation.
3928 *
3929 * called with nfs4_lock_state() held
3930 */ 3928 */
3931void 3929void
3932nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op) 3930nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op)
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index dc725deb4aa8..9cba295812f6 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -328,6 +328,7 @@ struct nfs4_replay {
328 unsigned int rp_buflen; 328 unsigned int rp_buflen;
329 char *rp_buf; 329 char *rp_buf;
330 struct knfsd_fh rp_openfh; 330 struct knfsd_fh rp_openfh;
331 struct mutex rp_mutex;
331 char rp_ibuf[NFSD4_REPLAY_ISIZE]; 332 char rp_ibuf[NFSD4_REPLAY_ISIZE];
332}; 333};
333 334
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 5abf6c942ddf..465e7799742a 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -599,7 +599,9 @@ extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
599 struct nfsd4_open *open, struct nfsd_net *nn); 599 struct nfsd4_open *open, struct nfsd_net *nn);
600extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp, 600extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
601 struct svc_fh *current_fh, struct nfsd4_open *open); 601 struct svc_fh *current_fh, struct nfsd4_open *open);
602extern void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status); 602extern void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate);
603extern void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
604 struct nfsd4_open *open, __be32 status);
603extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp, 605extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
604 struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc); 606 struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
605extern __be32 nfsd4_close(struct svc_rqst *rqstp, 607extern __be32 nfsd4_close(struct svc_rqst *rqstp,
@@ -630,6 +632,7 @@ extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
630extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp, 632extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
631 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid); 633 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
632extern void nfsd4_bump_seqid(struct nfsd4_compound_state *, __be32 nfserr); 634extern void nfsd4_bump_seqid(struct nfsd4_compound_state *, __be32 nfserr);
635
633#endif 636#endif
634 637
635/* 638/*