nfs41: pull decode_ds_addr from file layout to generic pnfs
authorPeng Tao <tao.peng@primarydata.com>
Thu, 29 May 2014 13:06:59 +0000 (21:06 +0800)
committerTom Haynes <loghyr@primarydata.com>
Tue, 3 Feb 2015 19:06:32 +0000 (11:06 -0800)
It can be reused by flexfile layout.

Reviewed-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Tom Haynes <Thomas.Haynes@primarydata.com>
fs/nfs/filelayout/filelayoutdev.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c

index fbfbb701159d7969fb3be9fb264b6cc8c4d58f9c..c7f6041a287fd79de055f1dbd6e7796e967b9a0a 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/nfs_fs.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
-#include <linux/sunrpc/addr.h>
 
 #include "../internal.h"
 #include "../nfs4session.h"
@@ -104,153 +103,6 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
        kfree(dsaddr);
 }
 
-/*
- * Currently only supports ipv4, ipv6 and one multi-path address.
- */
-static struct nfs4_pnfs_ds_addr *
-decode_ds_addr(struct net *net, struct xdr_stream *streamp, gfp_t gfp_flags)
-{
-       struct nfs4_pnfs_ds_addr *da = NULL;
-       char *buf, *portstr;
-       __be16 port;
-       int nlen, rlen;
-       int tmp[2];
-       __be32 *p;
-       char *netid, *match_netid;
-       size_t len, match_netid_len;
-       char *startsep = "";
-       char *endsep = "";
-
-
-       /* r_netid */
-       p = xdr_inline_decode(streamp, 4);
-       if (unlikely(!p))
-               goto out_err;
-       nlen = be32_to_cpup(p++);
-
-       p = xdr_inline_decode(streamp, nlen);
-       if (unlikely(!p))
-               goto out_err;
-
-       netid = kmalloc(nlen+1, gfp_flags);
-       if (unlikely(!netid))
-               goto out_err;
-
-       netid[nlen] = '\0';
-       memcpy(netid, p, nlen);
-
-       /* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */
-       p = xdr_inline_decode(streamp, 4);
-       if (unlikely(!p))
-               goto out_free_netid;
-       rlen = be32_to_cpup(p);
-
-       p = xdr_inline_decode(streamp, rlen);
-       if (unlikely(!p))
-               goto out_free_netid;
-
-       /* port is ".ABC.DEF", 8 chars max */
-       if (rlen > INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN + 8) {
-               dprintk("%s: Invalid address, length %d\n", __func__,
-                       rlen);
-               goto out_free_netid;
-       }
-       buf = kmalloc(rlen + 1, gfp_flags);
-       if (!buf) {
-               dprintk("%s: Not enough memory\n", __func__);
-               goto out_free_netid;
-       }
-       buf[rlen] = '\0';
-       memcpy(buf, p, rlen);
-
-       /* replace port '.' with '-' */
-       portstr = strrchr(buf, '.');
-       if (!portstr) {
-               dprintk("%s: Failed finding expected dot in port\n",
-                       __func__);
-               goto out_free_buf;
-       }
-       *portstr = '-';
-
-       /* find '.' between address and port */
-       portstr = strrchr(buf, '.');
-       if (!portstr) {
-               dprintk("%s: Failed finding expected dot between address and "
-                       "port\n", __func__);
-               goto out_free_buf;
-       }
-       *portstr = '\0';
-
-       da = kzalloc(sizeof(*da), gfp_flags);
-       if (unlikely(!da))
-               goto out_free_buf;
-
-       INIT_LIST_HEAD(&da->da_node);
-
-       if (!rpc_pton(net, buf, portstr-buf, (struct sockaddr *)&da->da_addr,
-                     sizeof(da->da_addr))) {
-               dprintk("%s: error parsing address %s\n", __func__, buf);
-               goto out_free_da;
-       }
-
-       portstr++;
-       sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]);
-       port = htons((tmp[0] << 8) | (tmp[1]));
-
-       switch (da->da_addr.ss_family) {
-       case AF_INET:
-               ((struct sockaddr_in *)&da->da_addr)->sin_port = port;
-               da->da_addrlen = sizeof(struct sockaddr_in);
-               match_netid = "tcp";
-               match_netid_len = 3;
-               break;
-
-       case AF_INET6:
-               ((struct sockaddr_in6 *)&da->da_addr)->sin6_port = port;
-               da->da_addrlen = sizeof(struct sockaddr_in6);
-               match_netid = "tcp6";
-               match_netid_len = 4;
-               startsep = "[";
-               endsep = "]";
-               break;
-
-       default:
-               dprintk("%s: unsupported address family: %u\n",
-                       __func__, da->da_addr.ss_family);
-               goto out_free_da;
-       }
-
-       if (nlen != match_netid_len || strncmp(netid, match_netid, nlen)) {
-               dprintk("%s: ERROR: r_netid \"%s\" != \"%s\"\n",
-                       __func__, netid, match_netid);
-               goto out_free_da;
-       }
-
-       /* save human readable address */
-       len = strlen(startsep) + strlen(buf) + strlen(endsep) + 7;
-       da->da_remotestr = kzalloc(len, gfp_flags);
-
-       /* NULL is ok, only used for dprintk */
-       if (da->da_remotestr)
-               snprintf(da->da_remotestr, len, "%s%s%s:%u", startsep,
-                        buf, endsep, ntohs(port));
-
-       dprintk("%s: Parsed DS addr %s\n", __func__, da->da_remotestr);
-       kfree(buf);
-       kfree(netid);
-       return da;
-
-out_free_da:
-       kfree(da);
-out_free_buf:
-       dprintk("%s: Error parsing DS addr: %s\n", __func__, buf);
-       kfree(buf);
-out_free_netid:
-       kfree(netid);
-out_err:
-       return NULL;
-}
-
 /* Decode opaque device data and return the result */
 struct nfs4_file_layout_dsaddr *
 nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
@@ -353,8 +205,8 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
 
                mp_count = be32_to_cpup(p); /* multipath count */
                for (j = 0; j < mp_count; j++) {
-                       da = decode_ds_addr(server->nfs_client->cl_net,
-                                           &stream, gfp_flags);
+                       da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
+                                                   &stream, gfp_flags);
                        if (da)
                                list_add_tail(&da->da_node, &dsaddrs);
                }
index b0168f1dd0728d3c7bb5b2eabcfd0ba17bcc3640..403d7bb67c4167722efeaa06c481714f9f8ca7c7 100644 (file)
@@ -312,6 +312,9 @@ void pnfs_generic_write_commit_done(struct rpc_task *task, void *data);
 void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds);
 struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs,
                                      gfp_t gfp_flags);
+struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
+                                                struct xdr_stream *xdr,
+                                                gfp_t gfp_flags);
 
 static inline struct nfs4_deviceid_node *
 nfs4_get_deviceid(struct nfs4_deviceid_node *d)
index 3bb2b74cf600414be7d70a3c8a345a669ee04dcc..81ec449138a8a8d0e353ff6410798aca6b6ea3a2 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
+#include <linux/sunrpc/addr.h>
 
 #include "internal.h"
 #include "pnfs.h"
@@ -532,3 +533,151 @@ out:
        return ds;
 }
 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_add);
+
+/*
+ * Currently only supports ipv4, ipv6 and one multi-path address.
+ */
+struct nfs4_pnfs_ds_addr *
+nfs4_decode_mp_ds_addr(struct net *net, struct xdr_stream *xdr, gfp_t gfp_flags)
+{
+       struct nfs4_pnfs_ds_addr *da = NULL;
+       char *buf, *portstr;
+       __be16 port;
+       int nlen, rlen;
+       int tmp[2];
+       __be32 *p;
+       char *netid, *match_netid;
+       size_t len, match_netid_len;
+       char *startsep = "";
+       char *endsep = "";
+
+
+       /* r_netid */
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_err;
+       nlen = be32_to_cpup(p++);
+
+       p = xdr_inline_decode(xdr, nlen);
+       if (unlikely(!p))
+               goto out_err;
+
+       netid = kmalloc(nlen+1, gfp_flags);
+       if (unlikely(!netid))
+               goto out_err;
+
+       netid[nlen] = '\0';
+       memcpy(netid, p, nlen);
+
+       /* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_free_netid;
+       rlen = be32_to_cpup(p);
+
+       p = xdr_inline_decode(xdr, rlen);
+       if (unlikely(!p))
+               goto out_free_netid;
+
+       /* port is ".ABC.DEF", 8 chars max */
+       if (rlen > INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN + 8) {
+               dprintk("%s: Invalid address, length %d\n", __func__,
+                       rlen);
+               goto out_free_netid;
+       }
+       buf = kmalloc(rlen + 1, gfp_flags);
+       if (!buf) {
+               dprintk("%s: Not enough memory\n", __func__);
+               goto out_free_netid;
+       }
+       buf[rlen] = '\0';
+       memcpy(buf, p, rlen);
+
+       /* replace port '.' with '-' */
+       portstr = strrchr(buf, '.');
+       if (!portstr) {
+               dprintk("%s: Failed finding expected dot in port\n",
+                       __func__);
+               goto out_free_buf;
+       }
+       *portstr = '-';
+
+       /* find '.' between address and port */
+       portstr = strrchr(buf, '.');
+       if (!portstr) {
+               dprintk("%s: Failed finding expected dot between address and "
+                       "port\n", __func__);
+               goto out_free_buf;
+       }
+       *portstr = '\0';
+
+       da = kzalloc(sizeof(*da), gfp_flags);
+       if (unlikely(!da))
+               goto out_free_buf;
+
+       INIT_LIST_HEAD(&da->da_node);
+
+       if (!rpc_pton(net, buf, portstr-buf, (struct sockaddr *)&da->da_addr,
+                     sizeof(da->da_addr))) {
+               dprintk("%s: error parsing address %s\n", __func__, buf);
+               goto out_free_da;
+       }
+
+       portstr++;
+       sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]);
+       port = htons((tmp[0] << 8) | (tmp[1]));
+
+       switch (da->da_addr.ss_family) {
+       case AF_INET:
+               ((struct sockaddr_in *)&da->da_addr)->sin_port = port;
+               da->da_addrlen = sizeof(struct sockaddr_in);
+               match_netid = "tcp";
+               match_netid_len = 3;
+               break;
+
+       case AF_INET6:
+               ((struct sockaddr_in6 *)&da->da_addr)->sin6_port = port;
+               da->da_addrlen = sizeof(struct sockaddr_in6);
+               match_netid = "tcp6";
+               match_netid_len = 4;
+               startsep = "[";
+               endsep = "]";
+               break;
+
+       default:
+               dprintk("%s: unsupported address family: %u\n",
+                       __func__, da->da_addr.ss_family);
+               goto out_free_da;
+       }
+
+       if (nlen != match_netid_len || strncmp(netid, match_netid, nlen)) {
+               dprintk("%s: ERROR: r_netid \"%s\" != \"%s\"\n",
+                       __func__, netid, match_netid);
+               goto out_free_da;
+       }
+
+       /* save human readable address */
+       len = strlen(startsep) + strlen(buf) + strlen(endsep) + 7;
+       da->da_remotestr = kzalloc(len, gfp_flags);
+
+       /* NULL is ok, only used for dprintk */
+       if (da->da_remotestr)
+               snprintf(da->da_remotestr, len, "%s%s%s:%u", startsep,
+                        buf, endsep, ntohs(port));
+
+       dprintk("%s: Parsed DS addr %s\n", __func__, da->da_remotestr);
+       kfree(buf);
+       kfree(netid);
+       return da;
+
+out_free_da:
+       kfree(da);
+out_free_buf:
+       dprintk("%s: Error parsing DS addr: %s\n", __func__, buf);
+       kfree(buf);
+out_free_netid:
+       kfree(netid);
+out_err:
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr);