diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 218 |
1 files changed, 212 insertions, 6 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 7c5d70efe720..1750d996f49f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -411,6 +411,15 @@ static int nfs_stat_to_errno(int); | |||
411 | #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ | 411 | #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ |
412 | decode_putfh_maxsz + \ | 412 | decode_putfh_maxsz + \ |
413 | op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) | 413 | op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) |
414 | #define NFS4_enc_fs_locations_sz \ | ||
415 | (compound_encode_hdr_maxsz + \ | ||
416 | encode_putfh_maxsz + \ | ||
417 | encode_getattr_maxsz) | ||
418 | #define NFS4_dec_fs_locations_sz \ | ||
419 | (compound_decode_hdr_maxsz + \ | ||
420 | decode_putfh_maxsz + \ | ||
421 | op_decode_hdr_maxsz + \ | ||
422 | nfs4_fattr_bitmap_maxsz) | ||
414 | 423 | ||
415 | static struct { | 424 | static struct { |
416 | unsigned int mode; | 425 | unsigned int mode; |
@@ -722,6 +731,13 @@ static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask) | |||
722 | bitmask[1] & nfs4_fsinfo_bitmap[1]); | 731 | bitmask[1] & nfs4_fsinfo_bitmap[1]); |
723 | } | 732 | } |
724 | 733 | ||
734 | static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask) | ||
735 | { | ||
736 | return encode_getattr_two(xdr, | ||
737 | bitmask[0] & nfs4_fs_locations_bitmap[0], | ||
738 | bitmask[1] & nfs4_fs_locations_bitmap[1]); | ||
739 | } | ||
740 | |||
725 | static int encode_getfh(struct xdr_stream *xdr) | 741 | static int encode_getfh(struct xdr_stream *xdr) |
726 | { | 742 | { |
727 | uint32_t *p; | 743 | uint32_t *p; |
@@ -2003,6 +2019,38 @@ out: | |||
2003 | } | 2019 | } |
2004 | 2020 | ||
2005 | /* | 2021 | /* |
2022 | * Encode FS_LOCATIONS request | ||
2023 | */ | ||
2024 | static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations_arg *args) | ||
2025 | { | ||
2026 | struct xdr_stream xdr; | ||
2027 | struct compound_hdr hdr = { | ||
2028 | .nops = 3, | ||
2029 | }; | ||
2030 | struct rpc_auth *auth = req->rq_task->tk_auth; | ||
2031 | int replen; | ||
2032 | int status; | ||
2033 | |||
2034 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
2035 | encode_compound_hdr(&xdr, &hdr); | ||
2036 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | ||
2037 | goto out; | ||
2038 | if ((status = encode_lookup(&xdr, args->name)) != 0) | ||
2039 | goto out; | ||
2040 | if ((status = encode_fs_locations(&xdr, args->bitmask)) != 0) | ||
2041 | goto out; | ||
2042 | /* set up reply | ||
2043 | * toplevel_status + OP_PUTFH + status | ||
2044 | * + OP_LOOKUP + status + OP_GETATTR + status = 7 | ||
2045 | */ | ||
2046 | replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2; | ||
2047 | xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page, | ||
2048 | 0, PAGE_SIZE); | ||
2049 | out: | ||
2050 | return status; | ||
2051 | } | ||
2052 | |||
2053 | /* | ||
2006 | * START OF "GENERIC" DECODE ROUTINES. | 2054 | * START OF "GENERIC" DECODE ROUTINES. |
2007 | * These may look a little ugly since they are imported from a "generic" | 2055 | * These may look a little ugly since they are imported from a "generic" |
2008 | * set of XDR encode/decode routines which are intended to be shared by | 2056 | * set of XDR encode/decode routines which are intended to be shared by |
@@ -2036,7 +2084,7 @@ out: | |||
2036 | } \ | 2084 | } \ |
2037 | } while (0) | 2085 | } while (0) |
2038 | 2086 | ||
2039 | static int decode_opaque_inline(struct xdr_stream *xdr, uint32_t *len, char **string) | 2087 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) |
2040 | { | 2088 | { |
2041 | uint32_t *p; | 2089 | uint32_t *p; |
2042 | 2090 | ||
@@ -2087,7 +2135,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | |||
2087 | static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp) | 2135 | static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp) |
2088 | { | 2136 | { |
2089 | uint32_t *p; | 2137 | uint32_t *p; |
2090 | uint32_t strlen; | 2138 | unsigned int strlen; |
2091 | char *str; | 2139 | char *str; |
2092 | 2140 | ||
2093 | READ_BUF(12); | 2141 | READ_BUF(12); |
@@ -2217,7 +2265,7 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, | |||
2217 | return 0; | 2265 | return 0; |
2218 | } | 2266 | } |
2219 | 2267 | ||
2220 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fsid *fsid) | 2268 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) |
2221 | { | 2269 | { |
2222 | uint32_t *p; | 2270 | uint32_t *p; |
2223 | 2271 | ||
@@ -2285,6 +2333,22 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t | |||
2285 | return 0; | 2333 | return 0; |
2286 | } | 2334 | } |
2287 | 2335 | ||
2336 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | ||
2337 | { | ||
2338 | uint32_t *p; | ||
2339 | |||
2340 | *fileid = 0; | ||
2341 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) | ||
2342 | return -EIO; | ||
2343 | if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { | ||
2344 | READ_BUF(8); | ||
2345 | READ64(*fileid); | ||
2346 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | ||
2347 | } | ||
2348 | dprintk("%s: fileid=%Lu\n", __FUNCTION__, (unsigned long long)*fileid); | ||
2349 | return 0; | ||
2350 | } | ||
2351 | |||
2288 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 2352 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
2289 | { | 2353 | { |
2290 | uint32_t *p; | 2354 | uint32_t *p; |
@@ -2336,6 +2400,116 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
2336 | return status; | 2400 | return status; |
2337 | } | 2401 | } |
2338 | 2402 | ||
2403 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) | ||
2404 | { | ||
2405 | int n; | ||
2406 | uint32_t *p; | ||
2407 | int status = 0; | ||
2408 | |||
2409 | READ_BUF(4); | ||
2410 | READ32(n); | ||
2411 | if (n < 0) | ||
2412 | goto out_eio; | ||
2413 | if (n == 0) | ||
2414 | goto root_path; | ||
2415 | dprintk("path "); | ||
2416 | path->ncomponents = 0; | ||
2417 | while (path->ncomponents < n) { | ||
2418 | struct nfs4_string *component = &path->components[path->ncomponents]; | ||
2419 | status = decode_opaque_inline(xdr, &component->len, &component->data); | ||
2420 | if (unlikely(status != 0)) | ||
2421 | goto out_eio; | ||
2422 | if (path->ncomponents != n) | ||
2423 | dprintk("/"); | ||
2424 | dprintk("%s", component->data); | ||
2425 | if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS) | ||
2426 | path->ncomponents++; | ||
2427 | else { | ||
2428 | dprintk("cannot parse %d components in path\n", n); | ||
2429 | goto out_eio; | ||
2430 | } | ||
2431 | } | ||
2432 | out: | ||
2433 | dprintk("\n"); | ||
2434 | return status; | ||
2435 | root_path: | ||
2436 | /* a root pathname is sent as a zero component4 */ | ||
2437 | path->ncomponents = 1; | ||
2438 | path->components[0].len=0; | ||
2439 | path->components[0].data=NULL; | ||
2440 | dprintk("path /\n"); | ||
2441 | goto out; | ||
2442 | out_eio: | ||
2443 | dprintk(" status %d", status); | ||
2444 | status = -EIO; | ||
2445 | goto out; | ||
2446 | } | ||
2447 | |||
2448 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) | ||
2449 | { | ||
2450 | int n; | ||
2451 | uint32_t *p; | ||
2452 | int status = -EIO; | ||
2453 | |||
2454 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) | ||
2455 | goto out; | ||
2456 | status = 0; | ||
2457 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) | ||
2458 | goto out; | ||
2459 | dprintk("%s: fsroot ", __FUNCTION__); | ||
2460 | status = decode_pathname(xdr, &res->fs_path); | ||
2461 | if (unlikely(status != 0)) | ||
2462 | goto out; | ||
2463 | READ_BUF(4); | ||
2464 | READ32(n); | ||
2465 | if (n <= 0) | ||
2466 | goto out_eio; | ||
2467 | res->nlocations = 0; | ||
2468 | while (res->nlocations < n) { | ||
2469 | int m; | ||
2470 | struct nfs4_fs_location *loc = &res->locations[res->nlocations]; | ||
2471 | |||
2472 | READ_BUF(4); | ||
2473 | READ32(m); | ||
2474 | if (m <= 0) | ||
2475 | goto out_eio; | ||
2476 | |||
2477 | loc->nservers = 0; | ||
2478 | dprintk("%s: servers ", __FUNCTION__); | ||
2479 | while (loc->nservers < m) { | ||
2480 | struct nfs4_string *server = &loc->servers[loc->nservers]; | ||
2481 | status = decode_opaque_inline(xdr, &server->len, &server->data); | ||
2482 | if (unlikely(status != 0)) | ||
2483 | goto out_eio; | ||
2484 | dprintk("%s ", server->data); | ||
2485 | if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) | ||
2486 | loc->nservers++; | ||
2487 | else { | ||
2488 | int i; | ||
2489 | dprintk("%s: using first %d of %d servers returned for location %d\n", __FUNCTION__, NFS4_FS_LOCATION_MAXSERVERS, m, res->nlocations); | ||
2490 | for (i = loc->nservers; i < m; i++) { | ||
2491 | int len; | ||
2492 | char *data; | ||
2493 | status = decode_opaque_inline(xdr, &len, &data); | ||
2494 | if (unlikely(status != 0)) | ||
2495 | goto out_eio; | ||
2496 | } | ||
2497 | } | ||
2498 | } | ||
2499 | status = decode_pathname(xdr, &loc->rootpath); | ||
2500 | if (unlikely(status != 0)) | ||
2501 | goto out_eio; | ||
2502 | if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) | ||
2503 | res->nlocations++; | ||
2504 | } | ||
2505 | out: | ||
2506 | dprintk("%s: fs_locations done, error = %d\n", __FUNCTION__, status); | ||
2507 | return status; | ||
2508 | out_eio: | ||
2509 | status = -EIO; | ||
2510 | goto out; | ||
2511 | } | ||
2512 | |||
2339 | static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 2513 | static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
2340 | { | 2514 | { |
2341 | uint32_t *p; | 2515 | uint32_t *p; |
@@ -2841,6 +3015,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
2841 | bitmap[2] = {0}, | 3015 | bitmap[2] = {0}, |
2842 | type; | 3016 | type; |
2843 | int status, fmode = 0; | 3017 | int status, fmode = 0; |
3018 | uint64_t fileid; | ||
2844 | 3019 | ||
2845 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 3020 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
2846 | goto xdr_error; | 3021 | goto xdr_error; |
@@ -2863,10 +3038,14 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
2863 | goto xdr_error; | 3038 | goto xdr_error; |
2864 | if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0) | 3039 | if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0) |
2865 | goto xdr_error; | 3040 | goto xdr_error; |
2866 | if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid_u.nfs4)) != 0) | 3041 | if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid)) != 0) |
2867 | goto xdr_error; | 3042 | goto xdr_error; |
2868 | if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0) | 3043 | if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0) |
2869 | goto xdr_error; | 3044 | goto xdr_error; |
3045 | if ((status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, | ||
3046 | struct nfs4_fs_locations, | ||
3047 | fattr))) != 0) | ||
3048 | goto xdr_error; | ||
2870 | if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0) | 3049 | if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0) |
2871 | goto xdr_error; | 3050 | goto xdr_error; |
2872 | fattr->mode |= fmode; | 3051 | fattr->mode |= fmode; |
@@ -2886,6 +3065,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
2886 | goto xdr_error; | 3065 | goto xdr_error; |
2887 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) | 3066 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) |
2888 | goto xdr_error; | 3067 | goto xdr_error; |
3068 | if ((status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid)) != 0) | ||
3069 | goto xdr_error; | ||
3070 | if (fattr->fileid == 0 && fileid != 0) | ||
3071 | fattr->fileid = fileid; | ||
2889 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) | 3072 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) |
2890 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; | 3073 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; |
2891 | xdr_error: | 3074 | xdr_error: |
@@ -3350,8 +3533,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
3350 | attrlen, recvd); | 3533 | attrlen, recvd); |
3351 | return -EINVAL; | 3534 | return -EINVAL; |
3352 | } | 3535 | } |
3353 | if (attrlen <= *acl_len) | 3536 | xdr_read_pages(xdr, attrlen); |
3354 | xdr_read_pages(xdr, attrlen); | ||
3355 | *acl_len = attrlen; | 3537 | *acl_len = attrlen; |
3356 | } else | 3538 | } else |
3357 | status = -EOPNOTSUPP; | 3539 | status = -EOPNOTSUPP; |
@@ -4211,6 +4393,29 @@ out: | |||
4211 | return status; | 4393 | return status; |
4212 | } | 4394 | } |
4213 | 4395 | ||
4396 | /* | ||
4397 | * FS_LOCATIONS request | ||
4398 | */ | ||
4399 | static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res) | ||
4400 | { | ||
4401 | struct xdr_stream xdr; | ||
4402 | struct compound_hdr hdr; | ||
4403 | int status; | ||
4404 | |||
4405 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | ||
4406 | status = decode_compound_hdr(&xdr, &hdr); | ||
4407 | if (status != 0) | ||
4408 | goto out; | ||
4409 | if ((status = decode_putfh(&xdr)) != 0) | ||
4410 | goto out; | ||
4411 | if ((status = decode_lookup(&xdr)) != 0) | ||
4412 | goto out; | ||
4413 | xdr_enter_page(&xdr, PAGE_SIZE); | ||
4414 | status = decode_getfattr(&xdr, &res->fattr, res->server); | ||
4415 | out: | ||
4416 | return status; | ||
4417 | } | ||
4418 | |||
4214 | uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) | 4419 | uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) |
4215 | { | 4420 | { |
4216 | uint32_t bitmap[2] = {0}; | 4421 | uint32_t bitmap[2] = {0}; |
@@ -4382,6 +4587,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
4382 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), | 4587 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), |
4383 | PROC(GETACL, enc_getacl, dec_getacl), | 4588 | PROC(GETACL, enc_getacl, dec_getacl), |
4384 | PROC(SETACL, enc_setacl, dec_setacl), | 4589 | PROC(SETACL, enc_setacl, dec_setacl), |
4590 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), | ||
4385 | }; | 4591 | }; |
4386 | 4592 | ||
4387 | struct rpc_version nfs_version4 = { | 4593 | struct rpc_version nfs_version4 = { |