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 | ||