diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2018-03-20 17:03:08 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2018-04-10 16:06:22 -0400 |
commit | 37c88763def8474bc0972fbd1adb0d21670104b7 (patch) | |
tree | 95a7e8b02256015ec220bc09eae30796daf73e7d /fs/nfs/nfs4xdr.c | |
parent | e8d8aa46be413930fb3e084f9a7e815f87f72f1f (diff) |
NFSv4; Clean up XDR encoding of type bitmap4
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 166 |
1 files changed, 72 insertions, 94 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6b08f6b1addf..80c5b519fd6a 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -958,6 +958,35 @@ static void encode_uint64(struct xdr_stream *xdr, u64 n) | |||
958 | WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0); | 958 | WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0); |
959 | } | 959 | } |
960 | 960 | ||
961 | static ssize_t xdr_encode_bitmap4(struct xdr_stream *xdr, | ||
962 | const __u32 *bitmap, size_t len) | ||
963 | { | ||
964 | ssize_t ret; | ||
965 | |||
966 | /* Trim empty words */ | ||
967 | while (len > 0 && bitmap[len-1] == 0) | ||
968 | len--; | ||
969 | ret = xdr_stream_encode_uint32_array(xdr, bitmap, len); | ||
970 | if (WARN_ON_ONCE(ret < 0)) | ||
971 | return ret; | ||
972 | return len; | ||
973 | } | ||
974 | |||
975 | static size_t mask_bitmap4(const __u32 *bitmap, const __u32 *mask, | ||
976 | __u32 *res, size_t len) | ||
977 | { | ||
978 | size_t i; | ||
979 | __u32 tmp; | ||
980 | |||
981 | while (len > 0 && (bitmap[len-1] == 0 || mask[len-1] == 0)) | ||
982 | len--; | ||
983 | for (i = len; i-- > 0;) { | ||
984 | tmp = bitmap[i] & mask[i]; | ||
985 | res[i] = tmp; | ||
986 | } | ||
987 | return len; | ||
988 | } | ||
989 | |||
961 | static void encode_nfs4_seqid(struct xdr_stream *xdr, | 990 | static void encode_nfs4_seqid(struct xdr_stream *xdr, |
962 | const struct nfs_seqid *seqid) | 991 | const struct nfs_seqid *seqid) |
963 | { | 992 | { |
@@ -1200,85 +1229,45 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg * | |||
1200 | create->server, create->server->attr_bitmask); | 1229 | create->server, create->server->attr_bitmask); |
1201 | } | 1230 | } |
1202 | 1231 | ||
1203 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) | 1232 | static void encode_getattr(struct xdr_stream *xdr, |
1204 | { | 1233 | const __u32 *bitmap, const __u32 *mask, size_t len, |
1205 | __be32 *p; | 1234 | struct compound_hdr *hdr) |
1206 | |||
1207 | encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); | ||
1208 | p = reserve_space(xdr, 8); | ||
1209 | *p++ = cpu_to_be32(1); | ||
1210 | *p = cpu_to_be32(bitmap); | ||
1211 | } | ||
1212 | |||
1213 | static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr) | ||
1214 | { | ||
1215 | __be32 *p; | ||
1216 | |||
1217 | encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); | ||
1218 | p = reserve_space(xdr, 12); | ||
1219 | *p++ = cpu_to_be32(2); | ||
1220 | *p++ = cpu_to_be32(bm0); | ||
1221 | *p = cpu_to_be32(bm1); | ||
1222 | } | ||
1223 | |||
1224 | static void | ||
1225 | encode_getattr_three(struct xdr_stream *xdr, | ||
1226 | uint32_t bm0, uint32_t bm1, uint32_t bm2, | ||
1227 | struct compound_hdr *hdr) | ||
1228 | { | 1235 | { |
1229 | __be32 *p; | 1236 | __u32 masked_bitmap[nfs4_fattr_bitmap_maxsz]; |
1230 | 1237 | ||
1231 | encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); | 1238 | encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr); |
1232 | if (bm2) { | 1239 | if (mask) { |
1233 | p = reserve_space(xdr, 16); | 1240 | if (WARN_ON_ONCE(len > ARRAY_SIZE(masked_bitmap))) |
1234 | *p++ = cpu_to_be32(3); | 1241 | len = ARRAY_SIZE(masked_bitmap); |
1235 | *p++ = cpu_to_be32(bm0); | 1242 | len = mask_bitmap4(bitmap, mask, masked_bitmap, len); |
1236 | *p++ = cpu_to_be32(bm1); | 1243 | bitmap = masked_bitmap; |
1237 | *p = cpu_to_be32(bm2); | ||
1238 | } else if (bm1) { | ||
1239 | p = reserve_space(xdr, 12); | ||
1240 | *p++ = cpu_to_be32(2); | ||
1241 | *p++ = cpu_to_be32(bm0); | ||
1242 | *p = cpu_to_be32(bm1); | ||
1243 | } else { | ||
1244 | p = reserve_space(xdr, 8); | ||
1245 | *p++ = cpu_to_be32(1); | ||
1246 | *p = cpu_to_be32(bm0); | ||
1247 | } | 1244 | } |
1245 | xdr_encode_bitmap4(xdr, bitmap, len); | ||
1248 | } | 1246 | } |
1249 | 1247 | ||
1250 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1248 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1251 | { | 1249 | { |
1252 | encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0], | 1250 | encode_getattr(xdr, nfs4_fattr_bitmap, bitmask, |
1253 | bitmask[1] & nfs4_fattr_bitmap[1], | 1251 | ARRAY_SIZE(nfs4_fattr_bitmap), hdr); |
1254 | bitmask[2] & nfs4_fattr_bitmap[2], | ||
1255 | hdr); | ||
1256 | } | 1252 | } |
1257 | 1253 | ||
1258 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, | 1254 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, |
1259 | const u32 *open_bitmap, | 1255 | const u32 *open_bitmap, |
1260 | struct compound_hdr *hdr) | 1256 | struct compound_hdr *hdr) |
1261 | { | 1257 | { |
1262 | encode_getattr_three(xdr, | 1258 | encode_getattr(xdr, open_bitmap, bitmask, 3, hdr); |
1263 | bitmask[0] & open_bitmap[0], | ||
1264 | bitmask[1] & open_bitmap[1], | ||
1265 | bitmask[2] & open_bitmap[2], | ||
1266 | hdr); | ||
1267 | } | 1259 | } |
1268 | 1260 | ||
1269 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1261 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1270 | { | 1262 | { |
1271 | encode_getattr_three(xdr, | 1263 | encode_getattr(xdr, nfs4_fsinfo_bitmap, bitmask, |
1272 | bitmask[0] & nfs4_fsinfo_bitmap[0], | 1264 | ARRAY_SIZE(nfs4_fsinfo_bitmap), hdr); |
1273 | bitmask[1] & nfs4_fsinfo_bitmap[1], | ||
1274 | bitmask[2] & nfs4_fsinfo_bitmap[2], | ||
1275 | hdr); | ||
1276 | } | 1265 | } |
1277 | 1266 | ||
1278 | static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1267 | static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1279 | { | 1268 | { |
1280 | encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0], | 1269 | encode_getattr(xdr, nfs4_fs_locations_bitmap, bitmask, |
1281 | bitmask[1] & nfs4_fs_locations_bitmap[1], hdr); | 1270 | ARRAY_SIZE(nfs4_fs_locations_bitmap), hdr); |
1282 | } | 1271 | } |
1283 | 1272 | ||
1284 | static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) | 1273 | static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
@@ -2559,13 +2548,17 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2559 | struct compound_hdr hdr = { | 2548 | struct compound_hdr hdr = { |
2560 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2549 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2561 | }; | 2550 | }; |
2551 | const __u32 nfs4_acl_bitmap[1] = { | ||
2552 | [0] = FATTR4_WORD0_ACL, | ||
2553 | }; | ||
2562 | uint32_t replen; | 2554 | uint32_t replen; |
2563 | 2555 | ||
2564 | encode_compound_hdr(xdr, req, &hdr); | 2556 | encode_compound_hdr(xdr, req, &hdr); |
2565 | encode_sequence(xdr, &args->seq_args, &hdr); | 2557 | encode_sequence(xdr, &args->seq_args, &hdr); |
2566 | encode_putfh(xdr, args->fh, &hdr); | 2558 | encode_putfh(xdr, args->fh, &hdr); |
2567 | replen = hdr.replen + op_decode_hdr_maxsz; | 2559 | replen = hdr.replen + op_decode_hdr_maxsz; |
2568 | encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); | 2560 | encode_getattr(xdr, nfs4_acl_bitmap, NULL, |
2561 | ARRAY_SIZE(nfs4_acl_bitmap), &hdr); | ||
2569 | 2562 | ||
2570 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, | 2563 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, |
2571 | args->acl_pages, 0, args->acl_len); | 2564 | args->acl_pages, 0, args->acl_len); |
@@ -2644,8 +2637,8 @@ static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2644 | encode_compound_hdr(xdr, req, &hdr); | 2637 | encode_compound_hdr(xdr, req, &hdr); |
2645 | encode_sequence(xdr, &args->seq_args, &hdr); | 2638 | encode_sequence(xdr, &args->seq_args, &hdr); |
2646 | encode_putfh(xdr, args->fh, &hdr); | 2639 | encode_putfh(xdr, args->fh, &hdr); |
2647 | encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0], | 2640 | encode_getattr(xdr, nfs4_pathconf_bitmap, args->bitmask, |
2648 | &hdr); | 2641 | ARRAY_SIZE(nfs4_pathconf_bitmap), &hdr); |
2649 | encode_nops(&hdr); | 2642 | encode_nops(&hdr); |
2650 | } | 2643 | } |
2651 | 2644 | ||
@@ -2663,8 +2656,8 @@ static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2663 | encode_compound_hdr(xdr, req, &hdr); | 2656 | encode_compound_hdr(xdr, req, &hdr); |
2664 | encode_sequence(xdr, &args->seq_args, &hdr); | 2657 | encode_sequence(xdr, &args->seq_args, &hdr); |
2665 | encode_putfh(xdr, args->fh, &hdr); | 2658 | encode_putfh(xdr, args->fh, &hdr); |
2666 | encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0], | 2659 | encode_getattr(xdr, nfs4_statfs_bitmap, args->bitmask, |
2667 | args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr); | 2660 | ARRAY_SIZE(nfs4_statfs_bitmap), &hdr); |
2668 | encode_nops(&hdr); | 2661 | encode_nops(&hdr); |
2669 | } | 2662 | } |
2670 | 2663 | ||
@@ -2684,7 +2677,7 @@ static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, | |||
2684 | encode_compound_hdr(xdr, req, &hdr); | 2677 | encode_compound_hdr(xdr, req, &hdr); |
2685 | encode_sequence(xdr, &args->seq_args, &hdr); | 2678 | encode_sequence(xdr, &args->seq_args, &hdr); |
2686 | encode_putfh(xdr, args->fhandle, &hdr); | 2679 | encode_putfh(xdr, args->fhandle, &hdr); |
2687 | encode_getattr_three(xdr, bitmask[0], bitmask[1], bitmask[2], &hdr); | 2680 | encode_getattr(xdr, bitmask, NULL, 3, &hdr); |
2688 | encode_nops(&hdr); | 2681 | encode_nops(&hdr); |
2689 | } | 2682 | } |
2690 | 2683 | ||
@@ -3218,34 +3211,27 @@ static int decode_ace(struct xdr_stream *xdr, void *ace) | |||
3218 | return -EIO; | 3211 | return -EIO; |
3219 | } | 3212 | } |
3220 | 3213 | ||
3221 | static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) | 3214 | static ssize_t |
3215 | decode_bitmap4(struct xdr_stream *xdr, uint32_t *bitmap, size_t sz) | ||
3222 | { | 3216 | { |
3223 | uint32_t bmlen; | 3217 | ssize_t ret; |
3224 | __be32 *p; | ||
3225 | |||
3226 | p = xdr_inline_decode(xdr, 4); | ||
3227 | if (unlikely(!p)) | ||
3228 | goto out_overflow; | ||
3229 | bmlen = be32_to_cpup(p); | ||
3230 | 3218 | ||
3231 | bitmap[0] = bitmap[1] = bitmap[2] = 0; | 3219 | ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz); |
3232 | p = xdr_inline_decode(xdr, (bmlen << 2)); | 3220 | if (likely(ret >= 0)) |
3233 | if (unlikely(!p)) | 3221 | return ret; |
3234 | goto out_overflow; | 3222 | if (ret == -EMSGSIZE) |
3235 | if (bmlen > 0) { | 3223 | return sz; |
3236 | bitmap[0] = be32_to_cpup(p++); | ||
3237 | if (bmlen > 1) { | ||
3238 | bitmap[1] = be32_to_cpup(p++); | ||
3239 | if (bmlen > 2) | ||
3240 | bitmap[2] = be32_to_cpup(p); | ||
3241 | } | ||
3242 | } | ||
3243 | return 0; | ||
3244 | out_overflow: | ||
3245 | print_overflow_msg(__func__, xdr); | 3224 | print_overflow_msg(__func__, xdr); |
3246 | return -EIO; | 3225 | return -EIO; |
3247 | } | 3226 | } |
3248 | 3227 | ||
3228 | static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) | ||
3229 | { | ||
3230 | ssize_t ret; | ||
3231 | ret = decode_bitmap4(xdr, bitmap, 3); | ||
3232 | return ret < 0 ? ret : 0; | ||
3233 | } | ||
3234 | |||
3249 | static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep) | 3235 | static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep) |
3250 | { | 3236 | { |
3251 | __be32 *p; | 3237 | __be32 *p; |
@@ -5471,21 +5457,13 @@ decode_savefh(struct xdr_stream *xdr) | |||
5471 | 5457 | ||
5472 | static int decode_setattr(struct xdr_stream *xdr) | 5458 | static int decode_setattr(struct xdr_stream *xdr) |
5473 | { | 5459 | { |
5474 | __be32 *p; | ||
5475 | uint32_t bmlen; | ||
5476 | int status; | 5460 | int status; |
5477 | 5461 | ||
5478 | status = decode_op_hdr(xdr, OP_SETATTR); | 5462 | status = decode_op_hdr(xdr, OP_SETATTR); |
5479 | if (status) | 5463 | if (status) |
5480 | return status; | 5464 | return status; |
5481 | p = xdr_inline_decode(xdr, 4); | 5465 | if (decode_bitmap4(xdr, NULL, 0) >= 0) |
5482 | if (unlikely(!p)) | ||
5483 | goto out_overflow; | ||
5484 | bmlen = be32_to_cpup(p); | ||
5485 | p = xdr_inline_decode(xdr, bmlen << 2); | ||
5486 | if (likely(p)) | ||
5487 | return 0; | 5466 | return 0; |
5488 | out_overflow: | ||
5489 | print_overflow_msg(__func__, xdr); | 5467 | print_overflow_msg(__func__, xdr); |
5490 | return -EIO; | 5468 | return -EIO; |
5491 | } | 5469 | } |