diff options
Diffstat (limited to 'fs/nfs/callback_xdr.c')
| -rw-r--r-- | fs/nfs/callback_xdr.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index a35582c9d444..f4ccfe6521ec 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
| @@ -166,9 +166,9 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound | |||
| 166 | if (unlikely(p == NULL)) | 166 | if (unlikely(p == NULL)) |
| 167 | return htonl(NFS4ERR_RESOURCE); | 167 | return htonl(NFS4ERR_RESOURCE); |
| 168 | hdr->minorversion = ntohl(*p++); | 168 | hdr->minorversion = ntohl(*p++); |
| 169 | /* Check minor version is zero or one. */ | 169 | /* Check for minor version support */ |
| 170 | if (hdr->minorversion <= 1) { | 170 | if (hdr->minorversion <= NFS4_MAX_MINOR_VERSION) { |
| 171 | hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */ | 171 | hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 and v4.2 */ |
| 172 | } else { | 172 | } else { |
| 173 | pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " | 173 | pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " |
| 174 | "illegal minor version %u!\n", | 174 | "illegal minor version %u!\n", |
| @@ -786,6 +786,26 @@ static void nfs4_cb_free_slot(struct cb_process_state *cps) | |||
| 786 | } | 786 | } |
| 787 | #endif /* CONFIG_NFS_V4_1 */ | 787 | #endif /* CONFIG_NFS_V4_1 */ |
| 788 | 788 | ||
| 789 | #ifdef CONFIG_NFS_V4_2 | ||
| 790 | static __be32 | ||
| 791 | preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op) | ||
| 792 | { | ||
| 793 | __be32 status = preprocess_nfs41_op(nop, op_nr, op); | ||
| 794 | if (status != htonl(NFS4ERR_OP_ILLEGAL)) | ||
| 795 | return status; | ||
| 796 | |||
| 797 | if (op_nr == OP_CB_OFFLOAD) | ||
| 798 | return htonl(NFS4ERR_NOTSUPP); | ||
| 799 | return htonl(NFS4ERR_OP_ILLEGAL); | ||
| 800 | } | ||
| 801 | #else /* CONFIG_NFS_V4_2 */ | ||
| 802 | static __be32 | ||
| 803 | preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op) | ||
| 804 | { | ||
| 805 | return htonl(NFS4ERR_MINOR_VERS_MISMATCH); | ||
| 806 | } | ||
| 807 | #endif /* CONFIG_NFS_V4_2 */ | ||
| 808 | |||
| 789 | static __be32 | 809 | static __be32 |
| 790 | preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) | 810 | preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) |
| 791 | { | 811 | { |
| @@ -801,8 +821,7 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) | |||
| 801 | return htonl(NFS_OK); | 821 | return htonl(NFS_OK); |
| 802 | } | 822 | } |
| 803 | 823 | ||
| 804 | static __be32 process_op(uint32_t minorversion, int nop, | 824 | static __be32 process_op(int nop, struct svc_rqst *rqstp, |
| 805 | struct svc_rqst *rqstp, | ||
| 806 | struct xdr_stream *xdr_in, void *argp, | 825 | struct xdr_stream *xdr_in, void *argp, |
| 807 | struct xdr_stream *xdr_out, void *resp, | 826 | struct xdr_stream *xdr_out, void *resp, |
| 808 | struct cb_process_state *cps) | 827 | struct cb_process_state *cps) |
| @@ -819,10 +838,22 @@ static __be32 process_op(uint32_t minorversion, int nop, | |||
| 819 | return status; | 838 | return status; |
| 820 | 839 | ||
| 821 | dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", | 840 | dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", |
| 822 | __func__, minorversion, nop, op_nr); | 841 | __func__, cps->minorversion, nop, op_nr); |
| 842 | |||
| 843 | switch (cps->minorversion) { | ||
| 844 | case 0: | ||
| 845 | status = preprocess_nfs4_op(op_nr, &op); | ||
| 846 | break; | ||
| 847 | case 1: | ||
| 848 | status = preprocess_nfs41_op(nop, op_nr, &op); | ||
| 849 | break; | ||
| 850 | case 2: | ||
| 851 | status = preprocess_nfs42_op(nop, op_nr, &op); | ||
| 852 | break; | ||
| 853 | default: | ||
| 854 | status = htonl(NFS4ERR_MINOR_VERS_MISMATCH); | ||
| 855 | } | ||
| 823 | 856 | ||
| 824 | status = minorversion ? preprocess_nfs41_op(nop, op_nr, &op) : | ||
| 825 | preprocess_nfs4_op(op_nr, &op); | ||
| 826 | if (status == htonl(NFS4ERR_OP_ILLEGAL)) | 857 | if (status == htonl(NFS4ERR_OP_ILLEGAL)) |
| 827 | op_nr = OP_CB_ILLEGAL; | 858 | op_nr = OP_CB_ILLEGAL; |
| 828 | if (status) | 859 | if (status) |
| @@ -885,14 +916,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
| 885 | return rpc_drop_reply; | 916 | return rpc_drop_reply; |
| 886 | } | 917 | } |
| 887 | 918 | ||
| 919 | cps.minorversion = hdr_arg.minorversion; | ||
| 888 | hdr_res.taglen = hdr_arg.taglen; | 920 | hdr_res.taglen = hdr_arg.taglen; |
| 889 | hdr_res.tag = hdr_arg.tag; | 921 | hdr_res.tag = hdr_arg.tag; |
| 890 | if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) | 922 | if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) |
| 891 | return rpc_system_err; | 923 | return rpc_system_err; |
| 892 | 924 | ||
| 893 | while (status == 0 && nops != hdr_arg.nops) { | 925 | while (status == 0 && nops != hdr_arg.nops) { |
| 894 | status = process_op(hdr_arg.minorversion, nops, rqstp, | 926 | status = process_op(nops, rqstp, &xdr_in, |
| 895 | &xdr_in, argp, &xdr_out, resp, &cps); | 927 | argp, &xdr_out, resp, &cps); |
| 896 | nops++; | 928 | nops++; |
| 897 | } | 929 | } |
| 898 | 930 | ||
