diff options
-rw-r--r-- | fs/nfs/nfs4_fs.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 80 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 30 |
4 files changed, 94 insertions, 22 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 5b7651171215..22a5f838ea58 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -219,7 +219,7 @@ extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct n | |||
219 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); | 219 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
220 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 220 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
221 | extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | 221 | extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, |
222 | struct nfs_fs_locations *fs_locations, struct page *page); | 222 | struct nfs4_fs_locations *fs_locations, struct page *page); |
223 | 223 | ||
224 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; | 224 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; |
225 | extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; | 225 | extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 768514dc0c4c..043223a0eda6 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3571,7 +3571,7 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen) | |||
3571 | } | 3571 | } |
3572 | 3572 | ||
3573 | int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | 3573 | int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, |
3574 | struct nfs_fs_locations *fs_locations, struct page *page) | 3574 | struct nfs4_fs_locations *fs_locations, struct page *page) |
3575 | { | 3575 | { |
3576 | struct nfs_server *server = NFS_SERVER(dir); | 3576 | struct nfs_server *server = NFS_SERVER(dir); |
3577 | u32 bitmask[2] = { | 3577 | u32 bitmask[2] = { |
@@ -3587,7 +3587,7 @@ int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | |||
3587 | struct rpc_message msg = { | 3587 | struct rpc_message msg = { |
3588 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], | 3588 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], |
3589 | .rpc_argp = &args, | 3589 | .rpc_argp = &args, |
3590 | .rpc_resp = &fs_locations, | 3590 | .rpc_resp = fs_locations, |
3591 | }; | 3591 | }; |
3592 | int status; | 3592 | int status; |
3593 | 3593 | ||
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; |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 15a20b815302..d6eea8348728 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -679,21 +679,31 @@ struct nfs4_server_caps_res { | |||
679 | u32 has_symlinks; | 679 | u32 has_symlinks; |
680 | }; | 680 | }; |
681 | 681 | ||
682 | struct nfs_fs_location { | 682 | struct nfs4_string { |
683 | unsigned int serverlen; | 683 | unsigned int len; |
684 | char * server; | 684 | char *data; |
685 | unsigned int rootpathlen; | ||
686 | char * rootpath; | ||
687 | }; | 685 | }; |
688 | 686 | ||
689 | #define NFS_FS_LOCATIONS_MAXENTRIES 10 | 687 | #define NFS4_PATHNAME_MAXCOMPONENTS 512 |
690 | struct nfs_fs_locations { | 688 | struct nfs4_pathname { |
689 | unsigned int ncomponents; | ||
690 | struct nfs4_string components[NFS4_PATHNAME_MAXCOMPONENTS]; | ||
691 | }; | ||
692 | |||
693 | #define NFS4_FS_LOCATION_MAXSERVERS 10 | ||
694 | struct nfs4_fs_location { | ||
695 | unsigned int nservers; | ||
696 | struct nfs4_string servers[NFS4_FS_LOCATION_MAXSERVERS]; | ||
697 | struct nfs4_pathname rootpath; | ||
698 | }; | ||
699 | |||
700 | #define NFS4_FS_LOCATIONS_MAXENTRIES 10 | ||
701 | struct nfs4_fs_locations { | ||
691 | struct nfs_fattr fattr; | 702 | struct nfs_fattr fattr; |
692 | const struct nfs_server *server; | 703 | const struct nfs_server *server; |
693 | unsigned int fs_pathlen; | 704 | struct nfs4_pathname fs_path; |
694 | char * fs_path; | ||
695 | int nlocations; | 705 | int nlocations; |
696 | struct nfs_fs_location locations[NFS_FS_LOCATIONS_MAXENTRIES]; | 706 | struct nfs4_fs_location locations[NFS4_FS_LOCATIONS_MAXENTRIES]; |
697 | }; | 707 | }; |
698 | 708 | ||
699 | struct nfs4_fs_locations_arg { | 709 | struct nfs4_fs_locations_arg { |