diff options
| -rw-r--r-- | fs/nfs/callback_proc.c | 25 | ||||
| -rw-r--r-- | fs/nfs/callback_xdr.c | 19 |
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 | ||
| 327 | unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) | 336 | unsigned 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) | |||
| 605 | static __be32 process_op(uint32_t minorversion, int nop, | 605 | static __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 | |||
| 639 | encode_hdr: | 650 | encode_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 | ||
