|
38 | 38 | #define CB_OP_RECALLSLOT_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
|
39 | 39 | #define CB_OP_NOTIFY_LOCK_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
|
40 | 40 | #endif /* CONFIG_NFS_V4_1 */
|
| 41 | +#ifdef CONFIG_NFS_V4_2 |
| 42 | +#define CB_OP_OFFLOAD_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) |
| 43 | +#endif /* CONFIG_NFS_V4_2 */ |
41 | 44 |
|
42 | 45 | #define NFSDBG_FACILITY NFSDBG_CALLBACK
|
43 | 46 |
|
@@ -527,7 +530,72 @@ static __be32 decode_notify_lock_args(struct svc_rqst *rqstp,
|
527 | 530 | }
|
528 | 531 |
|
529 | 532 | #endif /* CONFIG_NFS_V4_1 */
|
| 533 | +#ifdef CONFIG_NFS_V4_2 |
| 534 | +static __be32 decode_write_response(struct xdr_stream *xdr, |
| 535 | + struct cb_offloadargs *args) |
| 536 | +{ |
| 537 | + __be32 *p; |
| 538 | + |
| 539 | + /* skip the always zero field */ |
| 540 | + p = read_buf(xdr, 4); |
| 541 | + if (unlikely(!p)) |
| 542 | + goto out; |
| 543 | + p++; |
| 544 | + |
| 545 | + /* decode count, stable_how, verifier */ |
| 546 | + p = xdr_inline_decode(xdr, 8 + 4); |
| 547 | + if (unlikely(!p)) |
| 548 | + goto out; |
| 549 | + p = xdr_decode_hyper(p, &args->wr_count); |
| 550 | + args->wr_writeverf.committed = be32_to_cpup(p); |
| 551 | + p = xdr_inline_decode(xdr, NFS4_VERIFIER_SIZE); |
| 552 | + if (likely(p)) { |
| 553 | + memcpy(&args->wr_writeverf.verifier.data[0], p, |
| 554 | + NFS4_VERIFIER_SIZE); |
| 555 | + return 0; |
| 556 | + } |
| 557 | +out: |
| 558 | + return htonl(NFS4ERR_RESOURCE); |
| 559 | +} |
| 560 | + |
| 561 | +static __be32 decode_offload_args(struct svc_rqst *rqstp, |
| 562 | + struct xdr_stream *xdr, |
| 563 | + void *data) |
| 564 | +{ |
| 565 | + struct cb_offloadargs *args = data; |
| 566 | + __be32 *p; |
| 567 | + __be32 status; |
| 568 | + |
| 569 | + /* decode fh */ |
| 570 | + status = decode_fh(xdr, &args->coa_fh); |
| 571 | + if (unlikely(status != 0)) |
| 572 | + return status; |
| 573 | + |
| 574 | + /* decode stateid */ |
| 575 | + status = decode_stateid(xdr, &args->coa_stateid); |
| 576 | + if (unlikely(status != 0)) |
| 577 | + return status; |
530 | 578 |
|
| 579 | + /* decode status */ |
| 580 | + p = read_buf(xdr, 4); |
| 581 | + if (unlikely(!p)) |
| 582 | + goto out; |
| 583 | + args->error = ntohl(*p++); |
| 584 | + if (!args->error) { |
| 585 | + status = decode_write_response(xdr, args); |
| 586 | + if (unlikely(status != 0)) |
| 587 | + return status; |
| 588 | + } else { |
| 589 | + p = xdr_inline_decode(xdr, 8); |
| 590 | + if (unlikely(!p)) |
| 591 | + goto out; |
| 592 | + p = xdr_decode_hyper(p, &args->wr_count); |
| 593 | + } |
| 594 | + return 0; |
| 595 | +out: |
| 596 | + return htonl(NFS4ERR_RESOURCE); |
| 597 | +} |
| 598 | +#endif /* CONFIG_NFS_V4_2 */ |
531 | 599 | static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
|
532 | 600 | {
|
533 | 601 | if (unlikely(xdr_stream_encode_opaque(xdr, str, len) < 0))
|
@@ -773,7 +841,10 @@ preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op)
|
773 | 841 | if (status != htonl(NFS4ERR_OP_ILLEGAL))
|
774 | 842 | return status;
|
775 | 843 |
|
776 |
| - if (op_nr == OP_CB_OFFLOAD) |
| 844 | + if (op_nr == OP_CB_OFFLOAD) { |
| 845 | + *op = &callback_ops[op_nr]; |
| 846 | + return htonl(NFS_OK); |
| 847 | + } else |
777 | 848 | return htonl(NFS4ERR_NOTSUPP);
|
778 | 849 | return htonl(NFS4ERR_OP_ILLEGAL);
|
779 | 850 | }
|
@@ -974,6 +1045,13 @@ static struct callback_op callback_ops[] = {
|
974 | 1045 | .res_maxsize = CB_OP_NOTIFY_LOCK_RES_MAXSZ,
|
975 | 1046 | },
|
976 | 1047 | #endif /* CONFIG_NFS_V4_1 */
|
| 1048 | +#ifdef CONFIG_NFS_V4_2 |
| 1049 | + [OP_CB_OFFLOAD] = { |
| 1050 | + .process_op = nfs4_callback_offload, |
| 1051 | + .decode_args = decode_offload_args, |
| 1052 | + .res_maxsize = CB_OP_OFFLOAD_RES_MAXSZ, |
| 1053 | + }, |
| 1054 | +#endif /* CONFIG_NFS_V4_2 */ |
977 | 1055 | };
|
978 | 1056 |
|
979 | 1057 | /*
|
|
0 commit comments