aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/callback_proc.c25
-rw-r--r--fs/nfs/callback_xdr.c19
2 files changed, 32 insertions, 12 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 3d7edd65577b..4062f7690a33 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -143,9 +143,8 @@ int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const n
143 * Return success if the sequenceID is one more than what we last saw on 143 * Return success if the sequenceID is one more than what we last saw on
144 * this slot, accounting for wraparound. Increments the slot's sequence. 144 * this slot, accounting for wraparound. Increments the slot's sequence.
145 * 145 *
146 * We don't yet implement a duplicate request cache, so at this time 146 * We don't yet implement a duplicate request cache, instead we set the
147 * we will log replays, and process them as if we had not seen them before, 147 * back channel ca_maxresponsesize_cached to zero. This is OK for now
148 * but we don't bump the sequence in the slot. Not too worried about it,
149 * since we only currently implement idempotent callbacks anyway. 148 * since we only currently implement idempotent callbacks anyway.
150 * 149 *
151 * We have a single slot backchannel at this time, so we don't bother 150 * We have a single slot backchannel at this time, so we don't bother
@@ -174,9 +173,15 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
174 173
175 /* Replay */ 174 /* Replay */
176 if (args->csa_sequenceid == slot->seq_nr) { 175 if (args->csa_sequenceid == slot->seq_nr) {
177 dprintk("%s seqid %d is a replay - no DRC available\n", 176 dprintk("%s seqid %d is a replay\n",
178 __func__, args->csa_sequenceid); 177 __func__, args->csa_sequenceid);
179 return htonl(NFS4_OK); 178 /* Signal process_op to set this error on next op */
179 if (args->csa_cachethis == 0)
180 return htonl(NFS4ERR_RETRY_UNCACHED_REP);
181
182 /* The ca_maxresponsesize_cached is 0 with no DRC */
183 else if (args->csa_cachethis == 1)
184 return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
180 } 185 }
181 186
182 /* Wraparound */ 187 /* Wraparound */
@@ -319,9 +324,13 @@ out:
319 kfree(args->csa_rclists[i].rcl_refcalls); 324 kfree(args->csa_rclists[i].rcl_refcalls);
320 kfree(args->csa_rclists); 325 kfree(args->csa_rclists);
321 326
322 dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); 327 if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP))
323 res->csr_status = status; 328 res->csr_status = 0;
324 return res->csr_status; 329 else
330 res->csr_status = status;
331 dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
332 ntohl(status), ntohl(res->csr_status));
333 return status;
325} 334}
326 335
327unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) 336unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index a6f2ded72b17..08b430d922c4 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -605,7 +605,7 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op)
605static __be32 process_op(uint32_t minorversion, int nop, 605static __be32 process_op(uint32_t minorversion, int nop,
606 struct svc_rqst *rqstp, 606 struct svc_rqst *rqstp,
607 struct xdr_stream *xdr_in, void *argp, 607 struct xdr_stream *xdr_in, void *argp,
608 struct xdr_stream *xdr_out, void *resp) 608 struct xdr_stream *xdr_out, void *resp, int* drc_status)
609{ 609{
610 struct callback_op *op = &callback_ops[0]; 610 struct callback_op *op = &callback_ops[0];
611 unsigned int op_nr; 611 unsigned int op_nr;
@@ -628,6 +628,11 @@ static __be32 process_op(uint32_t minorversion, int nop,
628 if (status) 628 if (status)
629 goto encode_hdr; 629 goto encode_hdr;
630 630
631 if (*drc_status) {
632 status = *drc_status;
633 goto encode_hdr;
634 }
635
631 maxlen = xdr_out->end - xdr_out->p; 636 maxlen = xdr_out->end - xdr_out->p;
632 if (maxlen > 0 && maxlen < PAGE_SIZE) { 637 if (maxlen > 0 && maxlen < PAGE_SIZE) {
633 status = op->decode_args(rqstp, xdr_in, argp); 638 status = op->decode_args(rqstp, xdr_in, argp);
@@ -636,6 +641,12 @@ static __be32 process_op(uint32_t minorversion, int nop,
636 } else 641 } else
637 status = htonl(NFS4ERR_RESOURCE); 642 status = htonl(NFS4ERR_RESOURCE);
638 643
644 /* Only set by OP_CB_SEQUENCE processing */
645 if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
646 *drc_status = status;
647 status = 0;
648 }
649
639encode_hdr: 650encode_hdr:
640 res = encode_op_hdr(xdr_out, op_nr, status); 651 res = encode_op_hdr(xdr_out, op_nr, status);
641 if (unlikely(res)) 652 if (unlikely(res))
@@ -655,7 +666,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
655 struct cb_compound_hdr_res hdr_res = { NULL }; 666 struct cb_compound_hdr_res hdr_res = { NULL };
656 struct xdr_stream xdr_in, xdr_out; 667 struct xdr_stream xdr_in, xdr_out;
657 __be32 *p; 668 __be32 *p;
658 __be32 status; 669 __be32 status, drc_status = 0;
659 unsigned int nops = 0; 670 unsigned int nops = 0;
660 671
661 dprintk("%s: start\n", __func__); 672 dprintk("%s: start\n", __func__);
@@ -675,8 +686,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
675 return rpc_system_err; 686 return rpc_system_err;
676 687
677 while (status == 0 && nops != hdr_arg.nops) { 688 while (status == 0 && nops != hdr_arg.nops) {
678 status = process_op(hdr_arg.minorversion, nops, 689 status = process_op(hdr_arg.minorversion, nops, rqstp,
679 rqstp, &xdr_in, argp, &xdr_out, resp); 690 &xdr_in, argp, &xdr_out, resp, &drc_status);
680 nops++; 691 nops++;
681 } 692 }
682 693