diff options
-rw-r--r-- | fs/nfsd/nfs4callback.c | 60 | ||||
-rw-r--r-- | fs/nfsd/state.h | 1 |
2 files changed, 25 insertions, 36 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 58277859a467..cd58b7cd3f1a 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -224,7 +224,7 @@ static int nfs_cb_stat_to_errno(int status) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected, | 226 | static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected, |
227 | enum nfsstat4 *status) | 227 | int *status) |
228 | { | 228 | { |
229 | __be32 *p; | 229 | __be32 *p; |
230 | u32 op; | 230 | u32 op; |
@@ -235,7 +235,7 @@ static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected, | |||
235 | op = be32_to_cpup(p++); | 235 | op = be32_to_cpup(p++); |
236 | if (unlikely(op != expected)) | 236 | if (unlikely(op != expected)) |
237 | goto out_unexpected; | 237 | goto out_unexpected; |
238 | *status = be32_to_cpup(p); | 238 | *status = nfs_cb_stat_to_errno(be32_to_cpup(p)); |
239 | return 0; | 239 | return 0; |
240 | out_overflow: | 240 | out_overflow: |
241 | print_overflow_msg(__func__, xdr); | 241 | print_overflow_msg(__func__, xdr); |
@@ -446,22 +446,16 @@ out_overflow: | |||
446 | static int decode_cb_sequence4res(struct xdr_stream *xdr, | 446 | static int decode_cb_sequence4res(struct xdr_stream *xdr, |
447 | struct nfsd4_callback *cb) | 447 | struct nfsd4_callback *cb) |
448 | { | 448 | { |
449 | enum nfsstat4 nfserr; | ||
450 | int status; | 449 | int status; |
451 | 450 | ||
452 | if (cb->cb_minorversion == 0) | 451 | if (cb->cb_minorversion == 0) |
453 | return 0; | 452 | return 0; |
454 | 453 | ||
455 | status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr); | 454 | status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_status); |
456 | if (unlikely(status)) | 455 | if (unlikely(status || cb->cb_status)) |
457 | goto out; | 456 | return status; |
458 | if (unlikely(nfserr != NFS4_OK)) | 457 | |
459 | goto out_default; | 458 | return decode_cb_sequence4resok(xdr, cb); |
460 | status = decode_cb_sequence4resok(xdr, cb); | ||
461 | out: | ||
462 | return status; | ||
463 | out_default: | ||
464 | return nfs_cb_stat_to_errno(nfserr); | ||
465 | } | 459 | } |
466 | 460 | ||
467 | /* | 461 | /* |
@@ -524,26 +518,19 @@ static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, | |||
524 | struct nfsd4_callback *cb) | 518 | struct nfsd4_callback *cb) |
525 | { | 519 | { |
526 | struct nfs4_cb_compound_hdr hdr; | 520 | struct nfs4_cb_compound_hdr hdr; |
527 | enum nfsstat4 nfserr; | ||
528 | int status; | 521 | int status; |
529 | 522 | ||
530 | status = decode_cb_compound4res(xdr, &hdr); | 523 | status = decode_cb_compound4res(xdr, &hdr); |
531 | if (unlikely(status)) | 524 | if (unlikely(status)) |
532 | goto out; | 525 | return status; |
533 | 526 | ||
534 | if (cb != NULL) { | 527 | if (cb != NULL) { |
535 | status = decode_cb_sequence4res(xdr, cb); | 528 | status = decode_cb_sequence4res(xdr, cb); |
536 | if (unlikely(status)) | 529 | if (unlikely(status || cb->cb_status)) |
537 | goto out; | 530 | return status; |
538 | } | 531 | } |
539 | 532 | ||
540 | status = decode_cb_op_status(xdr, OP_CB_RECALL, &nfserr); | 533 | return decode_cb_op_status(xdr, OP_CB_RECALL, &cb->cb_status); |
541 | if (unlikely(status)) | ||
542 | goto out; | ||
543 | if (unlikely(nfserr != NFS4_OK)) | ||
544 | status = nfs_cb_stat_to_errno(nfserr); | ||
545 | out: | ||
546 | return status; | ||
547 | } | 534 | } |
548 | 535 | ||
549 | #ifdef CONFIG_NFSD_PNFS | 536 | #ifdef CONFIG_NFSD_PNFS |
@@ -621,24 +608,18 @@ static int nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp, | |||
621 | struct nfsd4_callback *cb) | 608 | struct nfsd4_callback *cb) |
622 | { | 609 | { |
623 | struct nfs4_cb_compound_hdr hdr; | 610 | struct nfs4_cb_compound_hdr hdr; |
624 | enum nfsstat4 nfserr; | ||
625 | int status; | 611 | int status; |
626 | 612 | ||
627 | status = decode_cb_compound4res(xdr, &hdr); | 613 | status = decode_cb_compound4res(xdr, &hdr); |
628 | if (unlikely(status)) | 614 | if (unlikely(status)) |
629 | goto out; | 615 | return status; |
616 | |||
630 | if (cb) { | 617 | if (cb) { |
631 | status = decode_cb_sequence4res(xdr, cb); | 618 | status = decode_cb_sequence4res(xdr, cb); |
632 | if (unlikely(status)) | 619 | if (unlikely(status || cb->cb_status)) |
633 | goto out; | 620 | return status; |
634 | } | 621 | } |
635 | status = decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &nfserr); | 622 | return decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &cb->cb_status); |
636 | if (unlikely(status)) | ||
637 | goto out; | ||
638 | if (unlikely(nfserr != NFS4_OK)) | ||
639 | status = nfs_cb_stat_to_errno(nfserr); | ||
640 | out: | ||
641 | return status; | ||
642 | } | 623 | } |
643 | #endif /* CONFIG_NFSD_PNFS */ | 624 | #endif /* CONFIG_NFSD_PNFS */ |
644 | 625 | ||
@@ -918,7 +899,8 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata) | |||
918 | 899 | ||
919 | if (clp->cl_minorversion) { | 900 | if (clp->cl_minorversion) { |
920 | /* No need for lock, access serialized in nfsd4_cb_prepare */ | 901 | /* No need for lock, access serialized in nfsd4_cb_prepare */ |
921 | ++clp->cl_cb_session->se_cb_seq_nr; | 902 | if (!task->tk_status) |
903 | ++clp->cl_cb_session->se_cb_seq_nr; | ||
922 | clear_bit(0, &clp->cl_cb_slot_busy); | 904 | clear_bit(0, &clp->cl_cb_slot_busy); |
923 | rpc_wake_up_next(&clp->cl_cb_waitq); | 905 | rpc_wake_up_next(&clp->cl_cb_waitq); |
924 | dprintk("%s: freed slot, new seqid=%d\n", __func__, | 906 | dprintk("%s: freed slot, new seqid=%d\n", __func__, |
@@ -935,6 +917,11 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata) | |||
935 | if (cb->cb_done) | 917 | if (cb->cb_done) |
936 | return; | 918 | return; |
937 | 919 | ||
920 | if (cb->cb_status) { | ||
921 | WARN_ON_ONCE(task->tk_status); | ||
922 | task->tk_status = cb->cb_status; | ||
923 | } | ||
924 | |||
938 | switch (cb->cb_ops->done(cb, task)) { | 925 | switch (cb->cb_ops->done(cb, task)) { |
939 | case 0: | 926 | case 0: |
940 | task->tk_status = 0; | 927 | task->tk_status = 0; |
@@ -1099,6 +1086,7 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, | |||
1099 | cb->cb_ops = ops; | 1086 | cb->cb_ops = ops; |
1100 | INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); | 1087 | INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); |
1101 | INIT_LIST_HEAD(&cb->cb_per_client); | 1088 | INIT_LIST_HEAD(&cb->cb_per_client); |
1089 | cb->cb_status = 0; | ||
1102 | cb->cb_done = true; | 1090 | cb->cb_done = true; |
1103 | } | 1091 | } |
1104 | 1092 | ||
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index bde45d90b746..e791985a7318 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -68,6 +68,7 @@ struct nfsd4_callback { | |||
68 | struct rpc_message cb_msg; | 68 | struct rpc_message cb_msg; |
69 | struct nfsd4_callback_ops *cb_ops; | 69 | struct nfsd4_callback_ops *cb_ops; |
70 | struct work_struct cb_work; | 70 | struct work_struct cb_work; |
71 | int cb_status; | ||
71 | bool cb_done; | 72 | bool cb_done; |
72 | }; | 73 | }; |
73 | 74 | ||