diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 233 |
1 files changed, 215 insertions, 18 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c191a9baa422..1dce12f41a4f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -113,7 +113,11 @@ static int nfs4_stat_to_errno(int); | |||
113 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) | 113 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) |
114 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) | 114 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) |
115 | #define encode_fsinfo_maxsz (encode_getattr_maxsz) | 115 | #define encode_fsinfo_maxsz (encode_getattr_maxsz) |
116 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 15) | 116 | /* The 5 accounts for the PNFS attributes, and assumes that at most three |
117 | * layout types will be returned. | ||
118 | */ | ||
119 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \ | ||
120 | nfs4_fattr_bitmap_maxsz + 4 + 8 + 5) | ||
117 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) | 121 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) |
118 | #define decode_renew_maxsz (op_decode_hdr_maxsz) | 122 | #define decode_renew_maxsz (op_decode_hdr_maxsz) |
119 | #define encode_setclientid_maxsz \ | 123 | #define encode_setclientid_maxsz \ |
@@ -314,6 +318,17 @@ static int nfs4_stat_to_errno(int); | |||
314 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) | 318 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) |
315 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) | 319 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) |
316 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) | 320 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) |
321 | #define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \ | ||
322 | encode_verifier_maxsz) | ||
323 | #define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \ | ||
324 | 2 /* nfs_cookie4 gdlr_cookie */ + \ | ||
325 | decode_verifier_maxsz \ | ||
326 | /* verifier4 gdlr_verifier */ + \ | ||
327 | 1 /* gdlr_deviceid_list count */ + \ | ||
328 | XDR_QUADLEN(NFS4_PNFS_GETDEVLIST_MAXNUM * \ | ||
329 | NFS4_DEVICEID4_SIZE) \ | ||
330 | /* gdlr_deviceid_list */ + \ | ||
331 | 1 /* bool gdlr_eof */) | ||
317 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ | 332 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ |
318 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) | 333 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) |
319 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ | 334 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ |
@@ -748,6 +763,14 @@ static int nfs4_stat_to_errno(int); | |||
748 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ | 763 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ |
749 | decode_sequence_maxsz + \ | 764 | decode_sequence_maxsz + \ |
750 | decode_reclaim_complete_maxsz) | 765 | decode_reclaim_complete_maxsz) |
766 | #define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \ | ||
767 | encode_sequence_maxsz + \ | ||
768 | encode_putfh_maxsz + \ | ||
769 | encode_getdevicelist_maxsz) | ||
770 | #define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \ | ||
771 | decode_sequence_maxsz + \ | ||
772 | decode_putfh_maxsz + \ | ||
773 | decode_getdevicelist_maxsz) | ||
751 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ | 774 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ |
752 | encode_sequence_maxsz +\ | 775 | encode_sequence_maxsz +\ |
753 | encode_getdeviceinfo_maxsz) | 776 | encode_getdeviceinfo_maxsz) |
@@ -1104,6 +1127,35 @@ static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm | |||
1104 | hdr->replen += decode_getattr_maxsz; | 1127 | hdr->replen += decode_getattr_maxsz; |
1105 | } | 1128 | } |
1106 | 1129 | ||
1130 | static void | ||
1131 | encode_getattr_three(struct xdr_stream *xdr, | ||
1132 | uint32_t bm0, uint32_t bm1, uint32_t bm2, | ||
1133 | struct compound_hdr *hdr) | ||
1134 | { | ||
1135 | __be32 *p; | ||
1136 | |||
1137 | p = reserve_space(xdr, 4); | ||
1138 | *p = cpu_to_be32(OP_GETATTR); | ||
1139 | if (bm2) { | ||
1140 | p = reserve_space(xdr, 16); | ||
1141 | *p++ = cpu_to_be32(3); | ||
1142 | *p++ = cpu_to_be32(bm0); | ||
1143 | *p++ = cpu_to_be32(bm1); | ||
1144 | *p = cpu_to_be32(bm2); | ||
1145 | } else if (bm1) { | ||
1146 | p = reserve_space(xdr, 12); | ||
1147 | *p++ = cpu_to_be32(2); | ||
1148 | *p++ = cpu_to_be32(bm0); | ||
1149 | *p = cpu_to_be32(bm1); | ||
1150 | } else { | ||
1151 | p = reserve_space(xdr, 8); | ||
1152 | *p++ = cpu_to_be32(1); | ||
1153 | *p = cpu_to_be32(bm0); | ||
1154 | } | ||
1155 | hdr->nops++; | ||
1156 | hdr->replen += decode_getattr_maxsz; | ||
1157 | } | ||
1158 | |||
1107 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1159 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1108 | { | 1160 | { |
1109 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], | 1161 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], |
@@ -1112,8 +1164,11 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c | |||
1112 | 1164 | ||
1113 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1165 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1114 | { | 1166 | { |
1115 | encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], | 1167 | encode_getattr_three(xdr, |
1116 | bitmask[1] & nfs4_fsinfo_bitmap[1], hdr); | 1168 | bitmask[0] & nfs4_fsinfo_bitmap[0], |
1169 | bitmask[1] & nfs4_fsinfo_bitmap[1], | ||
1170 | bitmask[2] & nfs4_fsinfo_bitmap[2], | ||
1171 | hdr); | ||
1117 | } | 1172 | } |
1118 | 1173 | ||
1119 | static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1174 | static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
@@ -1855,6 +1910,26 @@ static void encode_sequence(struct xdr_stream *xdr, | |||
1855 | 1910 | ||
1856 | #ifdef CONFIG_NFS_V4_1 | 1911 | #ifdef CONFIG_NFS_V4_1 |
1857 | static void | 1912 | static void |
1913 | encode_getdevicelist(struct xdr_stream *xdr, | ||
1914 | const struct nfs4_getdevicelist_args *args, | ||
1915 | struct compound_hdr *hdr) | ||
1916 | { | ||
1917 | __be32 *p; | ||
1918 | nfs4_verifier dummy = { | ||
1919 | .data = "dummmmmy", | ||
1920 | }; | ||
1921 | |||
1922 | p = reserve_space(xdr, 20); | ||
1923 | *p++ = cpu_to_be32(OP_GETDEVICELIST); | ||
1924 | *p++ = cpu_to_be32(args->layoutclass); | ||
1925 | *p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM); | ||
1926 | xdr_encode_hyper(p, 0ULL); /* cookie */ | ||
1927 | encode_nfs4_verifier(xdr, &dummy); | ||
1928 | hdr->nops++; | ||
1929 | hdr->replen += decode_getdevicelist_maxsz; | ||
1930 | } | ||
1931 | |||
1932 | static void | ||
1858 | encode_getdeviceinfo(struct xdr_stream *xdr, | 1933 | encode_getdeviceinfo(struct xdr_stream *xdr, |
1859 | const struct nfs4_getdeviceinfo_args *args, | 1934 | const struct nfs4_getdeviceinfo_args *args, |
1860 | struct compound_hdr *hdr) | 1935 | struct compound_hdr *hdr) |
@@ -1916,7 +1991,7 @@ encode_layoutcommit(struct xdr_stream *xdr, | |||
1916 | *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); | 1991 | *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); |
1917 | /* Only whole file layouts */ | 1992 | /* Only whole file layouts */ |
1918 | p = xdr_encode_hyper(p, 0); /* offset */ | 1993 | p = xdr_encode_hyper(p, 0); /* offset */ |
1919 | p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ | 1994 | p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */ |
1920 | *p++ = cpu_to_be32(0); /* reclaim */ | 1995 | *p++ = cpu_to_be32(0); /* reclaim */ |
1921 | p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); | 1996 | p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); |
1922 | *p++ = cpu_to_be32(1); /* newoffset = TRUE */ | 1997 | *p++ = cpu_to_be32(1); /* newoffset = TRUE */ |
@@ -2604,7 +2679,7 @@ static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, | |||
2604 | struct compound_hdr hdr = { | 2679 | struct compound_hdr hdr = { |
2605 | .nops = 0, | 2680 | .nops = 0, |
2606 | }; | 2681 | }; |
2607 | const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; | 2682 | const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; |
2608 | 2683 | ||
2609 | encode_compound_hdr(xdr, req, &hdr); | 2684 | encode_compound_hdr(xdr, req, &hdr); |
2610 | encode_setclientid_confirm(xdr, arg, &hdr); | 2685 | encode_setclientid_confirm(xdr, arg, &hdr); |
@@ -2748,7 +2823,7 @@ static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, | |||
2748 | struct compound_hdr hdr = { | 2823 | struct compound_hdr hdr = { |
2749 | .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), | 2824 | .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), |
2750 | }; | 2825 | }; |
2751 | const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; | 2826 | const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; |
2752 | 2827 | ||
2753 | encode_compound_hdr(xdr, req, &hdr); | 2828 | encode_compound_hdr(xdr, req, &hdr); |
2754 | encode_sequence(xdr, &args->la_seq_args, &hdr); | 2829 | encode_sequence(xdr, &args->la_seq_args, &hdr); |
@@ -2775,6 +2850,24 @@ static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, | |||
2775 | } | 2850 | } |
2776 | 2851 | ||
2777 | /* | 2852 | /* |
2853 | * Encode GETDEVICELIST request | ||
2854 | */ | ||
2855 | static void nfs4_xdr_enc_getdevicelist(struct rpc_rqst *req, | ||
2856 | struct xdr_stream *xdr, | ||
2857 | struct nfs4_getdevicelist_args *args) | ||
2858 | { | ||
2859 | struct compound_hdr hdr = { | ||
2860 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2861 | }; | ||
2862 | |||
2863 | encode_compound_hdr(xdr, req, &hdr); | ||
2864 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2865 | encode_putfh(xdr, args->fh, &hdr); | ||
2866 | encode_getdevicelist(xdr, args, &hdr); | ||
2867 | encode_nops(&hdr); | ||
2868 | } | ||
2869 | |||
2870 | /* | ||
2778 | * Encode GETDEVICEINFO request | 2871 | * Encode GETDEVICEINFO request |
2779 | */ | 2872 | */ |
2780 | static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, | 2873 | static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, |
@@ -3011,14 +3104,17 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) | |||
3011 | goto out_overflow; | 3104 | goto out_overflow; |
3012 | bmlen = be32_to_cpup(p); | 3105 | bmlen = be32_to_cpup(p); |
3013 | 3106 | ||
3014 | bitmap[0] = bitmap[1] = 0; | 3107 | bitmap[0] = bitmap[1] = bitmap[2] = 0; |
3015 | p = xdr_inline_decode(xdr, (bmlen << 2)); | 3108 | p = xdr_inline_decode(xdr, (bmlen << 2)); |
3016 | if (unlikely(!p)) | 3109 | if (unlikely(!p)) |
3017 | goto out_overflow; | 3110 | goto out_overflow; |
3018 | if (bmlen > 0) { | 3111 | if (bmlen > 0) { |
3019 | bitmap[0] = be32_to_cpup(p++); | 3112 | bitmap[0] = be32_to_cpup(p++); |
3020 | if (bmlen > 1) | 3113 | if (bmlen > 1) { |
3021 | bitmap[1] = be32_to_cpup(p); | 3114 | bitmap[1] = be32_to_cpup(p++); |
3115 | if (bmlen > 2) | ||
3116 | bitmap[2] = be32_to_cpup(p); | ||
3117 | } | ||
3022 | } | 3118 | } |
3023 | return 0; | 3119 | return 0; |
3024 | out_overflow: | 3120 | out_overflow: |
@@ -3050,8 +3146,9 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3 | |||
3050 | return ret; | 3146 | return ret; |
3051 | bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; | 3147 | bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; |
3052 | } else | 3148 | } else |
3053 | bitmask[0] = bitmask[1] = 0; | 3149 | bitmask[0] = bitmask[1] = bitmask[2] = 0; |
3054 | dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]); | 3150 | dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, |
3151 | bitmask[0], bitmask[1], bitmask[2]); | ||
3055 | return 0; | 3152 | return 0; |
3056 | } | 3153 | } |
3057 | 3154 | ||
@@ -4105,7 +4202,7 @@ out_overflow: | |||
4105 | static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) | 4202 | static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) |
4106 | { | 4203 | { |
4107 | __be32 *savep; | 4204 | __be32 *savep; |
4108 | uint32_t attrlen, bitmap[2] = {0}; | 4205 | uint32_t attrlen, bitmap[3] = {0}; |
4109 | int status; | 4206 | int status; |
4110 | 4207 | ||
4111 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4208 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
@@ -4131,7 +4228,7 @@ xdr_error: | |||
4131 | static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) | 4228 | static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) |
4132 | { | 4229 | { |
4133 | __be32 *savep; | 4230 | __be32 *savep; |
4134 | uint32_t attrlen, bitmap[2] = {0}; | 4231 | uint32_t attrlen, bitmap[3] = {0}; |
4135 | int status; | 4232 | int status; |
4136 | 4233 | ||
4137 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4234 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
@@ -4163,7 +4260,7 @@ xdr_error: | |||
4163 | static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) | 4260 | static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) |
4164 | { | 4261 | { |
4165 | __be32 *savep; | 4262 | __be32 *savep; |
4166 | uint32_t attrlen, bitmap[2] = {0}; | 4263 | uint32_t attrlen, bitmap[3] = {0}; |
4167 | int status; | 4264 | int status; |
4168 | 4265 | ||
4169 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4266 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
@@ -4303,7 +4400,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
4303 | { | 4400 | { |
4304 | __be32 *savep; | 4401 | __be32 *savep; |
4305 | uint32_t attrlen, | 4402 | uint32_t attrlen, |
4306 | bitmap[2] = {0}; | 4403 | bitmap[3] = {0}; |
4307 | int status; | 4404 | int status; |
4308 | 4405 | ||
4309 | status = decode_op_hdr(xdr, OP_GETATTR); | 4406 | status = decode_op_hdr(xdr, OP_GETATTR); |
@@ -4389,10 +4486,32 @@ static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4389 | return status; | 4486 | return status; |
4390 | } | 4487 | } |
4391 | 4488 | ||
4489 | /* | ||
4490 | * The prefered block size for layout directed io | ||
4491 | */ | ||
4492 | static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, | ||
4493 | uint32_t *res) | ||
4494 | { | ||
4495 | __be32 *p; | ||
4496 | |||
4497 | dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); | ||
4498 | *res = 0; | ||
4499 | if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { | ||
4500 | p = xdr_inline_decode(xdr, 4); | ||
4501 | if (unlikely(!p)) { | ||
4502 | print_overflow_msg(__func__, xdr); | ||
4503 | return -EIO; | ||
4504 | } | ||
4505 | *res = be32_to_cpup(p); | ||
4506 | bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; | ||
4507 | } | ||
4508 | return 0; | ||
4509 | } | ||
4510 | |||
4392 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | 4511 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) |
4393 | { | 4512 | { |
4394 | __be32 *savep; | 4513 | __be32 *savep; |
4395 | uint32_t attrlen, bitmap[2]; | 4514 | uint32_t attrlen, bitmap[3]; |
4396 | int status; | 4515 | int status; |
4397 | 4516 | ||
4398 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4517 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
@@ -4420,6 +4539,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | |||
4420 | status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); | 4539 | status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); |
4421 | if (status != 0) | 4540 | if (status != 0) |
4422 | goto xdr_error; | 4541 | goto xdr_error; |
4542 | status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize); | ||
4543 | if (status) | ||
4544 | goto xdr_error; | ||
4423 | 4545 | ||
4424 | status = verify_attr_len(xdr, savep, attrlen); | 4546 | status = verify_attr_len(xdr, savep, attrlen); |
4425 | xdr_error: | 4547 | xdr_error: |
@@ -4839,7 +4961,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
4839 | { | 4961 | { |
4840 | __be32 *savep; | 4962 | __be32 *savep; |
4841 | uint32_t attrlen, | 4963 | uint32_t attrlen, |
4842 | bitmap[2] = {0}; | 4964 | bitmap[3] = {0}; |
4843 | struct kvec *iov = req->rq_rcv_buf.head; | 4965 | struct kvec *iov = req->rq_rcv_buf.head; |
4844 | int status; | 4966 | int status; |
4845 | 4967 | ||
@@ -5268,6 +5390,53 @@ out_overflow: | |||
5268 | } | 5390 | } |
5269 | 5391 | ||
5270 | #if defined(CONFIG_NFS_V4_1) | 5392 | #if defined(CONFIG_NFS_V4_1) |
5393 | /* | ||
5394 | * TODO: Need to handle case when EOF != true; | ||
5395 | */ | ||
5396 | static int decode_getdevicelist(struct xdr_stream *xdr, | ||
5397 | struct pnfs_devicelist *res) | ||
5398 | { | ||
5399 | __be32 *p; | ||
5400 | int status, i; | ||
5401 | struct nfs_writeverf verftemp; | ||
5402 | |||
5403 | status = decode_op_hdr(xdr, OP_GETDEVICELIST); | ||
5404 | if (status) | ||
5405 | return status; | ||
5406 | |||
5407 | p = xdr_inline_decode(xdr, 8 + 8 + 4); | ||
5408 | if (unlikely(!p)) | ||
5409 | goto out_overflow; | ||
5410 | |||
5411 | /* TODO: Skip cookie for now */ | ||
5412 | p += 2; | ||
5413 | |||
5414 | /* Read verifier */ | ||
5415 | p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8); | ||
5416 | |||
5417 | res->num_devs = be32_to_cpup(p); | ||
5418 | |||
5419 | dprintk("%s: num_dev %d\n", __func__, res->num_devs); | ||
5420 | |||
5421 | if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) { | ||
5422 | printk(KERN_ERR "%s too many result dev_num %u\n", | ||
5423 | __func__, res->num_devs); | ||
5424 | return -EIO; | ||
5425 | } | ||
5426 | |||
5427 | p = xdr_inline_decode(xdr, | ||
5428 | res->num_devs * NFS4_DEVICEID4_SIZE + 4); | ||
5429 | if (unlikely(!p)) | ||
5430 | goto out_overflow; | ||
5431 | for (i = 0; i < res->num_devs; i++) | ||
5432 | p = xdr_decode_opaque_fixed(p, res->dev_id[i].data, | ||
5433 | NFS4_DEVICEID4_SIZE); | ||
5434 | res->eof = be32_to_cpup(p); | ||
5435 | return 0; | ||
5436 | out_overflow: | ||
5437 | print_overflow_msg(__func__, xdr); | ||
5438 | return -EIO; | ||
5439 | } | ||
5271 | 5440 | ||
5272 | static int decode_getdeviceinfo(struct xdr_stream *xdr, | 5441 | static int decode_getdeviceinfo(struct xdr_stream *xdr, |
5273 | struct pnfs_device *pdev) | 5442 | struct pnfs_device *pdev) |
@@ -5430,6 +5599,7 @@ static int decode_layoutcommit(struct xdr_stream *xdr, | |||
5430 | int status; | 5599 | int status; |
5431 | 5600 | ||
5432 | status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); | 5601 | status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); |
5602 | res->status = status; | ||
5433 | if (status) | 5603 | if (status) |
5434 | return status; | 5604 | return status; |
5435 | 5605 | ||
@@ -6542,6 +6712,32 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, | |||
6542 | } | 6712 | } |
6543 | 6713 | ||
6544 | /* | 6714 | /* |
6715 | * Decode GETDEVICELIST response | ||
6716 | */ | ||
6717 | static int nfs4_xdr_dec_getdevicelist(struct rpc_rqst *rqstp, | ||
6718 | struct xdr_stream *xdr, | ||
6719 | struct nfs4_getdevicelist_res *res) | ||
6720 | { | ||
6721 | struct compound_hdr hdr; | ||
6722 | int status; | ||
6723 | |||
6724 | dprintk("encoding getdevicelist!\n"); | ||
6725 | |||
6726 | status = decode_compound_hdr(xdr, &hdr); | ||
6727 | if (status != 0) | ||
6728 | goto out; | ||
6729 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6730 | if (status != 0) | ||
6731 | goto out; | ||
6732 | status = decode_putfh(xdr); | ||
6733 | if (status != 0) | ||
6734 | goto out; | ||
6735 | status = decode_getdevicelist(xdr, res->devlist); | ||
6736 | out: | ||
6737 | return status; | ||
6738 | } | ||
6739 | |||
6740 | /* | ||
6545 | * Decode GETDEVINFO response | 6741 | * Decode GETDEVINFO response |
6546 | */ | 6742 | */ |
6547 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, | 6743 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, |
@@ -6722,7 +6918,7 @@ out: | |||
6722 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 6918 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
6723 | int plus) | 6919 | int plus) |
6724 | { | 6920 | { |
6725 | uint32_t bitmap[2] = {0}; | 6921 | uint32_t bitmap[3] = {0}; |
6726 | uint32_t len; | 6922 | uint32_t len; |
6727 | __be32 *p = xdr_inline_decode(xdr, 4); | 6923 | __be32 *p = xdr_inline_decode(xdr, 4); |
6728 | if (unlikely(!p)) | 6924 | if (unlikely(!p)) |
@@ -6908,6 +7104,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
6908 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), | 7104 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), |
6909 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | 7105 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), |
6910 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), | 7106 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), |
7107 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), | ||
6911 | #endif /* CONFIG_NFS_V4_1 */ | 7108 | #endif /* CONFIG_NFS_V4_1 */ |
6912 | }; | 7109 | }; |
6913 | 7110 | ||