NFSv4: convert fs-locations-components to conform to RFC3530
authorManoj Naik <manoj@almaden.ibm.com>
Fri, 9 Jun 2006 13:34:23 +0000 (09:34 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 9 Jun 2006 13:34:23 +0000 (09:34 -0400)
Use component4-style formats for decoding list of servers and pathnames in
fs_locations.

Signed-off-by: Manoj Naik <manoj@almaden.ibm.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_xdr.h

index 5b76511..22a5f83 100644 (file)
@@ -219,7 +219,7 @@ extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct n
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
-               struct nfs_fs_locations *fs_locations, struct page *page);
+               struct nfs4_fs_locations *fs_locations, struct page *page);
 
 extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
 extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
index 768514d..043223a 100644 (file)
@@ -3571,7 +3571,7 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
 }
 
 int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
-               struct nfs_fs_locations *fs_locations, struct page *page)
+               struct nfs4_fs_locations *fs_locations, struct page *page)
 {
        struct nfs_server *server = NFS_SERVER(dir);
        u32 bitmask[2] = {
@@ -3587,7 +3587,7 @@ int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
                .rpc_argp = &args,
-               .rpc_resp = &fs_locations,
+               .rpc_resp = fs_locations,
        };
        int status;
 
index 7add313..f6a1ea7 100644 (file)
@@ -2377,7 +2377,43 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
        return status;
 }
 
-static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fs_locations *res)
+static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+{
+       int n;
+       uint32_t *p;
+       int status = 0;
+
+       READ_BUF(4);
+       READ32(n);
+       if (n <= 0)
+               goto out_eio;
+       dprintk("path ");
+       path->ncomponents = 0;
+       while (path->ncomponents < n) {
+               struct nfs4_string *component = &path->components[path->ncomponents];
+               status = decode_opaque_inline(xdr, &component->len, &component->data);
+               if (unlikely(status != 0))
+                       goto out_eio;
+               if (path->ncomponents != n)
+                       dprintk("/");
+               dprintk("%s", component->data);
+               if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS)
+                       path->ncomponents++;
+               else {
+                       dprintk("cannot parse %d components in path\n", n);
+                       goto out_eio;
+               }
+       }
+out:
+       dprintk("\n");
+       return status;
+out_eio:
+       dprintk(" status %d", status);
+       status = -EIO;
+       goto out;
+}
+
+static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
 {
        int n;
        uint32_t *p;
@@ -2388,7 +2424,8 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
        status = 0;
        if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
                goto out;
-       status = decode_opaque_inline(xdr, &res->fs_pathlen, &res->fs_path);
+       dprintk("%s: fsroot ", __FUNCTION__);
+       status = decode_pathname(xdr, &res->fs_path);
        if (unlikely(status != 0))
                goto out;
        READ_BUF(4);
@@ -2397,15 +2434,40 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
                goto out_eio;
        res->nlocations = 0;
        while (res->nlocations < n) {
-               struct nfs_fs_location *loc = &res->locations[res->nlocations];
+               int m;
+               struct nfs4_fs_location *loc = &res->locations[res->nlocations];
 
-               status = decode_opaque_inline(xdr, &loc->serverlen, &loc->server);
-               if (unlikely(status != 0))
+               READ_BUF(4);
+               READ32(m);
+               if (m <= 0)
                        goto out_eio;
-               status = decode_opaque_inline(xdr, &loc->rootpathlen, &loc->rootpath);
+
+               loc->nservers = 0;
+               dprintk("%s: servers ", __FUNCTION__);
+               while (loc->nservers < m) {
+                       struct nfs4_string *server = &loc->servers[loc->nservers];
+                       status = decode_opaque_inline(xdr, &server->len, &server->data);
+                       if (unlikely(status != 0))
+                               goto out_eio;
+                       dprintk("%s ", server->data);
+                       if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS)
+                               loc->nservers++;
+                       else {
+                               int i;
+                               dprintk("%s: using first %d of %d servers returned for location %d\n", __FUNCTION__, NFS4_FS_LOCATION_MAXSERVERS, m, res->nlocations);
+                               for (i = loc->nservers; i < m; i++) {
+                                       int len;
+                                       char *data;
+                                       status = decode_opaque_inline(xdr, &len, &data);
+                                       if (unlikely(status != 0))
+                                               goto out_eio;
+                               }
+                       }
+               }
+               status = decode_pathname(xdr, &loc->rootpath);
                if (unlikely(status != 0))
                        goto out_eio;
-               if (res->nlocations < NFS_FS_LOCATIONS_MAXENTRIES)
+               if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES)
                        res->nlocations++;
        }
 out:
@@ -2948,7 +3010,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
        if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0)
                goto xdr_error;
        if ((status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr,
-                                               struct nfs_fs_locations,
+                                               struct nfs4_fs_locations,
                                                fattr))) != 0)
                goto xdr_error;
        if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0)
@@ -4297,7 +4359,7 @@ out:
 /*
  * FS_LOCATIONS request
  */
-static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs_fs_locations *res)
+static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr;
index 15a20b8..d6eea83 100644 (file)
@@ -679,21 +679,31 @@ struct nfs4_server_caps_res {
        u32                             has_symlinks;
 };
 
-struct nfs_fs_location {
-       unsigned int serverlen;
-       char * server;
-       unsigned int rootpathlen;
-       char * rootpath;
+struct nfs4_string {
+       unsigned int len;
+       char *data;
 };
 
-#define NFS_FS_LOCATIONS_MAXENTRIES 10
-struct nfs_fs_locations {
+#define NFS4_PATHNAME_MAXCOMPONENTS 512
+struct nfs4_pathname {
+       unsigned int ncomponents;
+       struct nfs4_string components[NFS4_PATHNAME_MAXCOMPONENTS];
+};
+
+#define NFS4_FS_LOCATION_MAXSERVERS 10
+struct nfs4_fs_location {
+       unsigned int nservers;
+       struct nfs4_string servers[NFS4_FS_LOCATION_MAXSERVERS];
+       struct nfs4_pathname rootpath;
+};
+
+#define NFS4_FS_LOCATIONS_MAXENTRIES 10
+struct nfs4_fs_locations {
        struct nfs_fattr fattr;
        const struct nfs_server *server;
-       unsigned int fs_pathlen;
-       char * fs_path;
+       struct nfs4_pathname fs_path;
        int nlocations;
-       struct nfs_fs_location locations[NFS_FS_LOCATIONS_MAXENTRIES];
+       struct nfs4_fs_location locations[NFS4_FS_LOCATIONS_MAXENTRIES];
 };
 
 struct nfs4_fs_locations_arg {