diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 289 |
1 files changed, 248 insertions, 41 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 7c5d70efe720..3dd413f52da1 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -58,7 +58,7 @@ | |||
| 58 | /* Mapping from NFS error code to "errno" error code. */ | 58 | /* Mapping from NFS error code to "errno" error code. */ |
| 59 | #define errno_NFSERR_IO EIO | 59 | #define errno_NFSERR_IO EIO |
| 60 | 60 | ||
| 61 | static int nfs_stat_to_errno(int); | 61 | static int nfs4_stat_to_errno(int); |
| 62 | 62 | ||
| 63 | /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ | 63 | /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ |
| 64 | #ifdef DEBUG | 64 | #ifdef DEBUG |
| @@ -128,7 +128,7 @@ static int nfs_stat_to_errno(int); | |||
| 128 | #define decode_link_maxsz (op_decode_hdr_maxsz + 5) | 128 | #define decode_link_maxsz (op_decode_hdr_maxsz + 5) |
| 129 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ | 129 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ |
| 130 | 1 + nfs4_name_maxsz + \ | 130 | 1 + nfs4_name_maxsz + \ |
| 131 | nfs4_path_maxsz + \ | 131 | 1 + \ |
| 132 | nfs4_fattr_maxsz) | 132 | nfs4_fattr_maxsz) |
| 133 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) | 133 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) |
| 134 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ | 134 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ |
| @@ -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; |
| @@ -520,7 +529,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s | |||
| 520 | if (iap->ia_valid & ATTR_MODE) | 529 | if (iap->ia_valid & ATTR_MODE) |
| 521 | len += 4; | 530 | len += 4; |
| 522 | if (iap->ia_valid & ATTR_UID) { | 531 | if (iap->ia_valid & ATTR_UID) { |
| 523 | owner_namelen = nfs_map_uid_to_name(server->nfs4_state, iap->ia_uid, owner_name); | 532 | owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name); |
| 524 | if (owner_namelen < 0) { | 533 | if (owner_namelen < 0) { |
| 525 | printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n", | 534 | printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n", |
| 526 | iap->ia_uid); | 535 | iap->ia_uid); |
| @@ -532,7 +541,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s | |||
| 532 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); | 541 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); |
| 533 | } | 542 | } |
| 534 | if (iap->ia_valid & ATTR_GID) { | 543 | if (iap->ia_valid & ATTR_GID) { |
| 535 | owner_grouplen = nfs_map_gid_to_group(server->nfs4_state, iap->ia_gid, owner_group); | 544 | owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group); |
| 536 | if (owner_grouplen < 0) { | 545 | if (owner_grouplen < 0) { |
| 537 | printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n", | 546 | printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n", |
| 538 | iap->ia_gid); | 547 | iap->ia_gid); |
| @@ -664,9 +673,9 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c | |||
| 664 | 673 | ||
| 665 | switch (create->ftype) { | 674 | switch (create->ftype) { |
| 666 | case NF4LNK: | 675 | case NF4LNK: |
| 667 | RESERVE_SPACE(4 + create->u.symlink->len); | 676 | RESERVE_SPACE(4); |
| 668 | WRITE32(create->u.symlink->len); | 677 | WRITE32(create->u.symlink.len); |
| 669 | WRITEMEM(create->u.symlink->name, create->u.symlink->len); | 678 | xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); |
| 670 | break; | 679 | break; |
| 671 | 680 | ||
| 672 | case NF4BLK: case NF4CHR: | 681 | case NF4BLK: case NF4CHR: |
| @@ -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; |
| @@ -1144,7 +1160,7 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con | |||
| 1144 | return 0; | 1160 | return 0; |
| 1145 | } | 1161 | } |
| 1146 | 1162 | ||
| 1147 | static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client_stateid) | 1163 | static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid) |
| 1148 | { | 1164 | { |
| 1149 | uint32_t *p; | 1165 | uint32_t *p; |
| 1150 | 1166 | ||
| @@ -1230,7 +1246,7 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien | |||
| 1230 | return 0; | 1246 | return 0; |
| 1231 | } | 1247 | } |
| 1232 | 1248 | ||
| 1233 | static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_client *client_state) | 1249 | static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state) |
| 1234 | { | 1250 | { |
| 1235 | uint32_t *p; | 1251 | uint32_t *p; |
| 1236 | 1252 | ||
| @@ -1929,7 +1945,7 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const str | |||
| 1929 | /* | 1945 | /* |
| 1930 | * a RENEW request | 1946 | * a RENEW request |
| 1931 | */ | 1947 | */ |
| 1932 | static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) | 1948 | static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) |
| 1933 | { | 1949 | { |
| 1934 | struct xdr_stream xdr; | 1950 | struct xdr_stream xdr; |
| 1935 | struct compound_hdr hdr = { | 1951 | struct compound_hdr hdr = { |
| @@ -1959,7 +1975,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nf | |||
| 1959 | /* | 1975 | /* |
| 1960 | * a SETCLIENTID_CONFIRM request | 1976 | * a SETCLIENTID_CONFIRM request |
| 1961 | */ | 1977 | */ |
| 1962 | static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) | 1978 | static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) |
| 1963 | { | 1979 | { |
| 1964 | struct xdr_stream xdr; | 1980 | struct xdr_stream xdr; |
| 1965 | struct compound_hdr hdr = { | 1981 | struct compound_hdr hdr = { |
| @@ -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 | ||
| @@ -2079,15 +2127,15 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | |||
| 2079 | } | 2127 | } |
| 2080 | READ32(nfserr); | 2128 | READ32(nfserr); |
| 2081 | if (nfserr != NFS_OK) | 2129 | if (nfserr != NFS_OK) |
| 2082 | return -nfs_stat_to_errno(nfserr); | 2130 | return -nfs4_stat_to_errno(nfserr); |
| 2083 | return 0; | 2131 | return 0; |
| 2084 | } | 2132 | } |
| 2085 | 2133 | ||
| 2086 | /* Dummy routine */ | 2134 | /* Dummy routine */ |
| 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 nfs_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; |
| @@ -2462,7 +2636,7 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t | |||
| 2462 | return 0; | 2636 | return 0; |
| 2463 | } | 2637 | } |
| 2464 | 2638 | ||
| 2465 | static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *uid) | 2639 | static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid) |
| 2466 | { | 2640 | { |
| 2467 | uint32_t len, *p; | 2641 | uint32_t len, *p; |
| 2468 | 2642 | ||
| @@ -2486,7 +2660,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
| 2486 | return 0; | 2660 | return 0; |
| 2487 | } | 2661 | } |
| 2488 | 2662 | ||
| 2489 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *gid) | 2663 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid) |
| 2490 | { | 2664 | { |
| 2491 | uint32_t len, *p; | 2665 | uint32_t len, *p; |
| 2492 | 2666 | ||
| @@ -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,18 +3038,22 @@ 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; |
| 2873 | if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0) | 3052 | if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0) |
| 2874 | goto xdr_error; | 3053 | goto xdr_error; |
| 2875 | if ((status = decode_attr_owner(xdr, bitmap, server->nfs4_state, &fattr->uid)) != 0) | 3054 | if ((status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid)) != 0) |
| 2876 | goto xdr_error; | 3055 | goto xdr_error; |
| 2877 | if ((status = decode_attr_group(xdr, bitmap, server->nfs4_state, &fattr->gid)) != 0) | 3056 | if ((status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid)) != 0) |
| 2878 | goto xdr_error; | 3057 | goto xdr_error; |
| 2879 | if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0) | 3058 | if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0) |
| 2880 | goto xdr_error; | 3059 | goto xdr_error; |
| @@ -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: |
| @@ -3071,7 +3254,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | |||
| 3071 | if (decode_space_limit(xdr, &res->maxsize) < 0) | 3254 | if (decode_space_limit(xdr, &res->maxsize) < 0) |
| 3072 | return -EIO; | 3255 | return -EIO; |
| 3073 | } | 3256 | } |
| 3074 | return decode_ace(xdr, NULL, res->server->nfs4_state); | 3257 | return decode_ace(xdr, NULL, res->server->nfs_client); |
| 3075 | } | 3258 | } |
| 3076 | 3259 | ||
| 3077 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | 3260 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) |
| @@ -3172,7 +3355,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3172 | struct kvec *iov = rcvbuf->head; | 3355 | struct kvec *iov = rcvbuf->head; |
| 3173 | unsigned int nr, pglen = rcvbuf->page_len; | 3356 | unsigned int nr, pglen = rcvbuf->page_len; |
| 3174 | uint32_t *end, *entry, *p, *kaddr; | 3357 | uint32_t *end, *entry, *p, *kaddr; |
| 3175 | uint32_t len, attrlen; | 3358 | uint32_t len, attrlen, xlen; |
| 3176 | int hdrlen, recvd, status; | 3359 | int hdrlen, recvd, status; |
| 3177 | 3360 | ||
| 3178 | status = decode_op_hdr(xdr, OP_READDIR); | 3361 | status = decode_op_hdr(xdr, OP_READDIR); |
| @@ -3194,10 +3377,10 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3194 | 3377 | ||
| 3195 | BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); | 3378 | BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); |
| 3196 | kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); | 3379 | kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); |
| 3197 | end = (uint32_t *) ((char *)p + pglen + readdir->pgbase); | 3380 | end = p + ((pglen + readdir->pgbase) >> 2); |
| 3198 | entry = p; | 3381 | entry = p; |
| 3199 | for (nr = 0; *p++; nr++) { | 3382 | for (nr = 0; *p++; nr++) { |
| 3200 | if (p + 3 > end) | 3383 | if (end - p < 3) |
| 3201 | goto short_pkt; | 3384 | goto short_pkt; |
| 3202 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); | 3385 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); |
| 3203 | p += 2; /* cookie */ | 3386 | p += 2; /* cookie */ |
| @@ -3206,18 +3389,19 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3206 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); | 3389 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); |
| 3207 | goto err_unmap; | 3390 | goto err_unmap; |
| 3208 | } | 3391 | } |
| 3209 | dprintk("filename = %*s\n", len, (char *)p); | 3392 | xlen = XDR_QUADLEN(len); |
| 3210 | p += XDR_QUADLEN(len); | 3393 | if (end - p < xlen + 1) |
| 3211 | if (p + 1 > end) | ||
| 3212 | goto short_pkt; | 3394 | goto short_pkt; |
| 3395 | dprintk("filename = %*s\n", len, (char *)p); | ||
| 3396 | p += xlen; | ||
| 3213 | len = ntohl(*p++); /* bitmap length */ | 3397 | len = ntohl(*p++); /* bitmap length */ |
| 3214 | p += len; | 3398 | if (end - p < len + 1) |
| 3215 | if (p + 1 > end) | ||
| 3216 | goto short_pkt; | 3399 | goto short_pkt; |
| 3400 | p += len; | ||
| 3217 | attrlen = XDR_QUADLEN(ntohl(*p++)); | 3401 | attrlen = XDR_QUADLEN(ntohl(*p++)); |
| 3218 | p += attrlen; /* attributes */ | 3402 | if (end - p < attrlen + 2) |
| 3219 | if (p + 2 > end) | ||
| 3220 | goto short_pkt; | 3403 | goto short_pkt; |
| 3404 | p += attrlen; /* attributes */ | ||
| 3221 | entry = p; | 3405 | entry = p; |
| 3222 | } | 3406 | } |
| 3223 | if (!nr && (entry[0] != 0 || entry[1] == 0)) | 3407 | if (!nr && (entry[0] != 0 || entry[1] == 0)) |
| @@ -3350,8 +3534,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
| 3350 | attrlen, recvd); | 3534 | attrlen, recvd); |
| 3351 | return -EINVAL; | 3535 | return -EINVAL; |
| 3352 | } | 3536 | } |
| 3353 | if (attrlen <= *acl_len) | 3537 | xdr_read_pages(xdr, attrlen); |
| 3354 | xdr_read_pages(xdr, attrlen); | ||
| 3355 | *acl_len = attrlen; | 3538 | *acl_len = attrlen; |
| 3356 | } else | 3539 | } else |
| 3357 | status = -EOPNOTSUPP; | 3540 | status = -EOPNOTSUPP; |
| @@ -3382,7 +3565,7 @@ static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) | |||
| 3382 | return 0; | 3565 | return 0; |
| 3383 | } | 3566 | } |
| 3384 | 3567 | ||
| 3385 | static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp) | 3568 | static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) |
| 3386 | { | 3569 | { |
| 3387 | uint32_t *p; | 3570 | uint32_t *p; |
| 3388 | uint32_t opnum; | 3571 | uint32_t opnum; |
| @@ -3415,7 +3598,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp) | |||
| 3415 | READ_BUF(len); | 3598 | READ_BUF(len); |
| 3416 | return -NFSERR_CLID_INUSE; | 3599 | return -NFSERR_CLID_INUSE; |
| 3417 | } else | 3600 | } else |
| 3418 | return -nfs_stat_to_errno(nfserr); | 3601 | return -nfs4_stat_to_errno(nfserr); |
| 3419 | 3602 | ||
| 3420 | return 0; | 3603 | return 0; |
| 3421 | } | 3604 | } |
| @@ -4073,7 +4256,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsi | |||
| 4073 | if (!status) | 4256 | if (!status) |
| 4074 | status = decode_fsinfo(&xdr, fsinfo); | 4257 | status = decode_fsinfo(&xdr, fsinfo); |
| 4075 | if (!status) | 4258 | if (!status) |
| 4076 | status = -nfs_stat_to_errno(hdr.status); | 4259 | status = -nfs4_stat_to_errno(hdr.status); |
| 4077 | return status; | 4260 | return status; |
| 4078 | } | 4261 | } |
| 4079 | 4262 | ||
| @@ -4152,7 +4335,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) | |||
| 4152 | * a SETCLIENTID request | 4335 | * a SETCLIENTID request |
| 4153 | */ | 4336 | */ |
| 4154 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, | 4337 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, |
| 4155 | struct nfs4_client *clp) | 4338 | struct nfs_client *clp) |
| 4156 | { | 4339 | { |
| 4157 | struct xdr_stream xdr; | 4340 | struct xdr_stream xdr; |
| 4158 | struct compound_hdr hdr; | 4341 | struct compound_hdr hdr; |
| @@ -4163,7 +4346,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, | |||
| 4163 | if (!status) | 4346 | if (!status) |
| 4164 | status = decode_setclientid(&xdr, clp); | 4347 | status = decode_setclientid(&xdr, clp); |
| 4165 | if (!status) | 4348 | if (!status) |
| 4166 | status = -nfs_stat_to_errno(hdr.status); | 4349 | status = -nfs4_stat_to_errno(hdr.status); |
| 4167 | return status; | 4350 | return status; |
| 4168 | } | 4351 | } |
| 4169 | 4352 | ||
| @@ -4185,7 +4368,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s | |||
| 4185 | if (!status) | 4368 | if (!status) |
| 4186 | status = decode_fsinfo(&xdr, fsinfo); | 4369 | status = decode_fsinfo(&xdr, fsinfo); |
| 4187 | if (!status) | 4370 | if (!status) |
| 4188 | status = -nfs_stat_to_errno(hdr.status); | 4371 | status = -nfs4_stat_to_errno(hdr.status); |
| 4189 | return status; | 4372 | return status; |
| 4190 | } | 4373 | } |
| 4191 | 4374 | ||
| @@ -4211,6 +4394,29 @@ out: | |||
| 4211 | return status; | 4394 | return status; |
| 4212 | } | 4395 | } |
| 4213 | 4396 | ||
| 4397 | /* | ||
| 4398 | * FS_LOCATIONS request | ||
| 4399 | */ | ||
| 4400 | static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res) | ||
| 4401 | { | ||
| 4402 | struct xdr_stream xdr; | ||
| 4403 | struct compound_hdr hdr; | ||
| 4404 | int status; | ||
| 4405 | |||
| 4406 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | ||
| 4407 | status = decode_compound_hdr(&xdr, &hdr); | ||
| 4408 | if (status != 0) | ||
| 4409 | goto out; | ||
| 4410 | if ((status = decode_putfh(&xdr)) != 0) | ||
| 4411 | goto out; | ||
| 4412 | if ((status = decode_lookup(&xdr)) != 0) | ||
| 4413 | goto out; | ||
| 4414 | xdr_enter_page(&xdr, PAGE_SIZE); | ||
| 4415 | status = decode_getfattr(&xdr, &res->fattr, res->server); | ||
| 4416 | out: | ||
| 4417 | return status; | ||
| 4418 | } | ||
| 4419 | |||
| 4214 | uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) | 4420 | uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) |
| 4215 | { | 4421 | { |
| 4216 | uint32_t bitmap[2] = {0}; | 4422 | uint32_t bitmap[2] = {0}; |
| @@ -4315,7 +4521,7 @@ static struct { | |||
| 4315 | * This one is used jointly by NFSv2 and NFSv3. | 4521 | * This one is used jointly by NFSv2 and NFSv3. |
| 4316 | */ | 4522 | */ |
| 4317 | static int | 4523 | static int |
| 4318 | nfs_stat_to_errno(int stat) | 4524 | nfs4_stat_to_errno(int stat) |
| 4319 | { | 4525 | { |
| 4320 | int i; | 4526 | int i; |
| 4321 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { | 4527 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { |
| @@ -4382,6 +4588,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
| 4382 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), | 4588 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), |
| 4383 | PROC(GETACL, enc_getacl, dec_getacl), | 4589 | PROC(GETACL, enc_getacl, dec_getacl), |
| 4384 | PROC(SETACL, enc_setacl, dec_setacl), | 4590 | PROC(SETACL, enc_setacl, dec_setacl), |
| 4591 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), | ||
| 4385 | }; | 4592 | }; |
| 4386 | 4593 | ||
| 4387 | struct rpc_version nfs_version4 = { | 4594 | struct rpc_version nfs_version4 = { |
