diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 80 |
1 files changed, 71 insertions, 9 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 7add3137b6b6..f6a1ea7df374 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -2377,7 +2377,43 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
2377 | return status; | 2377 | return status; |
2378 | } | 2378 | } |
2379 | 2379 | ||
2380 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fs_locations *res) | 2380 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) |
2381 | { | ||
2382 | int n; | ||
2383 | uint32_t *p; | ||
2384 | int status = 0; | ||
2385 | |||
2386 | READ_BUF(4); | ||
2387 | READ32(n); | ||
2388 | if (n <= 0) | ||
2389 | goto out_eio; | ||
2390 | dprintk("path "); | ||
2391 | path->ncomponents = 0; | ||
2392 | while (path->ncomponents < n) { | ||
2393 | struct nfs4_string *component = &path->components[path->ncomponents]; | ||
2394 | status = decode_opaque_inline(xdr, &component->len, &component->data); | ||
2395 | if (unlikely(status != 0)) | ||
2396 | goto out_eio; | ||
2397 | if (path->ncomponents != n) | ||
2398 | dprintk("/"); | ||
2399 | dprintk("%s", component->data); | ||
2400 | if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS) | ||
2401 | path->ncomponents++; | ||
2402 | else { | ||
2403 | dprintk("cannot parse %d components in path\n", n); | ||
2404 | goto out_eio; | ||
2405 | } | ||
2406 | } | ||
2407 | out: | ||
2408 | dprintk("\n"); | ||
2409 | return status; | ||
2410 | out_eio: | ||
2411 | dprintk(" status %d", status); | ||
2412 | status = -EIO; | ||
2413 | goto out; | ||
2414 | } | ||
2415 | |||
2416 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) | ||
2381 | { | 2417 | { |
2382 | int n; | 2418 | int n; |
2383 | uint32_t *p; | 2419 | uint32_t *p; |
@@ -2388,7 +2424,8 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
2388 | status = 0; | 2424 | status = 0; |
2389 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) | 2425 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) |
2390 | goto out; | 2426 | goto out; |
2391 | status = decode_opaque_inline(xdr, &res->fs_pathlen, &res->fs_path); | 2427 | dprintk("%s: fsroot ", __FUNCTION__); |
2428 | status = decode_pathname(xdr, &res->fs_path); | ||
2392 | if (unlikely(status != 0)) | 2429 | if (unlikely(status != 0)) |
2393 | goto out; | 2430 | goto out; |
2394 | READ_BUF(4); | 2431 | READ_BUF(4); |
@@ -2397,15 +2434,40 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
2397 | goto out_eio; | 2434 | goto out_eio; |
2398 | res->nlocations = 0; | 2435 | res->nlocations = 0; |
2399 | while (res->nlocations < n) { | 2436 | while (res->nlocations < n) { |
2400 | struct nfs_fs_location *loc = &res->locations[res->nlocations]; | 2437 | int m; |
2438 | struct nfs4_fs_location *loc = &res->locations[res->nlocations]; | ||
2401 | 2439 | ||
2402 | status = decode_opaque_inline(xdr, &loc->serverlen, &loc->server); | 2440 | READ_BUF(4); |
2403 | if (unlikely(status != 0)) | 2441 | READ32(m); |
2442 | if (m <= 0) | ||
2404 | goto out_eio; | 2443 | goto out_eio; |
2405 | status = decode_opaque_inline(xdr, &loc->rootpathlen, &loc->rootpath); | 2444 | |
2445 | loc->nservers = 0; | ||
2446 | dprintk("%s: servers ", __FUNCTION__); | ||
2447 | while (loc->nservers < m) { | ||
2448 | struct nfs4_string *server = &loc->servers[loc->nservers]; | ||
2449 | status = decode_opaque_inline(xdr, &server->len, &server->data); | ||
2450 | if (unlikely(status != 0)) | ||
2451 | goto out_eio; | ||
2452 | dprintk("%s ", server->data); | ||
2453 | if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) | ||
2454 | loc->nservers++; | ||
2455 | else { | ||
2456 | int i; | ||
2457 | dprintk("%s: using first %d of %d servers returned for location %d\n", __FUNCTION__, NFS4_FS_LOCATION_MAXSERVERS, m, res->nlocations); | ||
2458 | for (i = loc->nservers; i < m; i++) { | ||
2459 | int len; | ||
2460 | char *data; | ||
2461 | status = decode_opaque_inline(xdr, &len, &data); | ||
2462 | if (unlikely(status != 0)) | ||
2463 | goto out_eio; | ||
2464 | } | ||
2465 | } | ||
2466 | } | ||
2467 | status = decode_pathname(xdr, &loc->rootpath); | ||
2406 | if (unlikely(status != 0)) | 2468 | if (unlikely(status != 0)) |
2407 | goto out_eio; | 2469 | goto out_eio; |
2408 | if (res->nlocations < NFS_FS_LOCATIONS_MAXENTRIES) | 2470 | if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) |
2409 | res->nlocations++; | 2471 | res->nlocations++; |
2410 | } | 2472 | } |
2411 | out: | 2473 | out: |
@@ -2948,7 +3010,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
2948 | if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0) | 3010 | if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0) |
2949 | goto xdr_error; | 3011 | goto xdr_error; |
2950 | if ((status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, | 3012 | if ((status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, |
2951 | struct nfs_fs_locations, | 3013 | struct nfs4_fs_locations, |
2952 | fattr))) != 0) | 3014 | fattr))) != 0) |
2953 | goto xdr_error; | 3015 | goto xdr_error; |
2954 | if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0) | 3016 | if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0) |
@@ -4297,7 +4359,7 @@ out: | |||
4297 | /* | 4359 | /* |
4298 | * FS_LOCATIONS request | 4360 | * FS_LOCATIONS request |
4299 | */ | 4361 | */ |
4300 | static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs_fs_locations *res) | 4362 | static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res) |
4301 | { | 4363 | { |
4302 | struct xdr_stream xdr; | 4364 | struct xdr_stream xdr; |
4303 | struct compound_hdr hdr; | 4365 | struct compound_hdr hdr; |