aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c4
-rw-r--r--fs/nfs/nfs4xdr.c80
-rw-r--r--include/linux/nfs_xdr.h30
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
219extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 219extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
220extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); 220extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
221extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, 221extern 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
224extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; 224extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
225extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; 225extern 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
3573int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, 3573int 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
2380static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fs_locations *res) 2380static 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 }
2407out:
2408 dprintk("\n");
2409 return status;
2410out_eio:
2411 dprintk(" status %d", status);
2412 status = -EIO;
2413 goto out;
2414}
2415
2416static 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 }
2411out: 2473out:
@@ -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 */
4300static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs_fs_locations *res) 4362static 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
682struct nfs_fs_location { 682struct 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
690struct nfs_fs_locations { 688struct nfs4_pathname {
689 unsigned int ncomponents;
690 struct nfs4_string components[NFS4_PATHNAME_MAXCOMPONENTS];
691};
692
693#define NFS4_FS_LOCATION_MAXSERVERS 10
694struct 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
701struct 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
699struct nfs4_fs_locations_arg { 709struct nfs4_fs_locations_arg {