aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/filelayout
diff options
context:
space:
mode:
authorPeng Tao <tao.peng@primarydata.com>2014-05-29 09:06:59 -0400
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:32 -0500
commit6b7f3cf96364eaf597940cb5c68a682894829915 (patch)
tree532e1216ff4e72da9600f5504d862ced8e0fd8db /fs/nfs/filelayout
parent875ae0694be48f3e3bdddd435b79abf52b680299 (diff)
nfs41: pull decode_ds_addr from file layout to generic pnfs
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>
Diffstat (limited to 'fs/nfs/filelayout')
-rw-r--r--fs/nfs/filelayout/filelayoutdev.c152
1 files changed, 2 insertions, 150 deletions
diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c
index fbfbb701159d..c7f6041a287f 100644
--- a/fs/nfs/filelayout/filelayoutdev.c
+++ b/fs/nfs/filelayout/filelayoutdev.c
@@ -31,7 +31,6 @@
31#include <linux/nfs_fs.h> 31#include <linux/nfs_fs.h>
32#include <linux/vmalloc.h> 32#include <linux/vmalloc.h>
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/sunrpc/addr.h>
35 34
36#include "../internal.h" 35#include "../internal.h"
37#include "../nfs4session.h" 36#include "../nfs4session.h"
@@ -104,153 +103,6 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
104 kfree(dsaddr); 103 kfree(dsaddr);
105} 104}
106 105
107/*
108 * Currently only supports ipv4, ipv6 and one multi-path address.
109 */
110static struct nfs4_pnfs_ds_addr *
111decode_ds_addr(struct net *net, struct xdr_stream *streamp, gfp_t gfp_flags)
112{
113 struct nfs4_pnfs_ds_addr *da = NULL;
114 char *buf, *portstr;
115 __be16 port;
116 int nlen, rlen;
117 int tmp[2];
118 __be32 *p;
119 char *netid, *match_netid;
120 size_t len, match_netid_len;
121 char *startsep = "";
122 char *endsep = "";
123
124
125 /* r_netid */
126 p = xdr_inline_decode(streamp, 4);
127 if (unlikely(!p))
128 goto out_err;
129 nlen = be32_to_cpup(p++);
130
131 p = xdr_inline_decode(streamp, nlen);
132 if (unlikely(!p))
133 goto out_err;
134
135 netid = kmalloc(nlen+1, gfp_flags);
136 if (unlikely(!netid))
137 goto out_err;
138
139 netid[nlen] = '\0';
140 memcpy(netid, p, nlen);
141
142 /* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */
143 p = xdr_inline_decode(streamp, 4);
144 if (unlikely(!p))
145 goto out_free_netid;
146 rlen = be32_to_cpup(p);
147
148 p = xdr_inline_decode(streamp, rlen);
149 if (unlikely(!p))
150 goto out_free_netid;
151
152 /* port is ".ABC.DEF", 8 chars max */
153 if (rlen > INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN + 8) {
154 dprintk("%s: Invalid address, length %d\n", __func__,
155 rlen);
156 goto out_free_netid;
157 }
158 buf = kmalloc(rlen + 1, gfp_flags);
159 if (!buf) {
160 dprintk("%s: Not enough memory\n", __func__);
161 goto out_free_netid;
162 }
163 buf[rlen] = '\0';
164 memcpy(buf, p, rlen);
165
166 /* replace port '.' with '-' */
167 portstr = strrchr(buf, '.');
168 if (!portstr) {
169 dprintk("%s: Failed finding expected dot in port\n",
170 __func__);
171 goto out_free_buf;
172 }
173 *portstr = '-';
174
175 /* find '.' between address and port */
176 portstr = strrchr(buf, '.');
177 if (!portstr) {
178 dprintk("%s: Failed finding expected dot between address and "
179 "port\n", __func__);
180 goto out_free_buf;
181 }
182 *portstr = '\0';
183
184 da = kzalloc(sizeof(*da), gfp_flags);
185 if (unlikely(!da))
186 goto out_free_buf;
187
188 INIT_LIST_HEAD(&da->da_node);
189
190 if (!rpc_pton(net, buf, portstr-buf, (struct sockaddr *)&da->da_addr,
191 sizeof(da->da_addr))) {
192 dprintk("%s: error parsing address %s\n", __func__, buf);
193 goto out_free_da;
194 }
195
196 portstr++;
197 sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]);
198 port = htons((tmp[0] << 8) | (tmp[1]));
199
200 switch (da->da_addr.ss_family) {
201 case AF_INET:
202 ((struct sockaddr_in *)&da->da_addr)->sin_port = port;
203 da->da_addrlen = sizeof(struct sockaddr_in);
204 match_netid = "tcp";
205 match_netid_len = 3;
206 break;
207
208 case AF_INET6:
209 ((struct sockaddr_in6 *)&da->da_addr)->sin6_port = port;
210 da->da_addrlen = sizeof(struct sockaddr_in6);
211 match_netid = "tcp6";
212 match_netid_len = 4;
213 startsep = "[";
214 endsep = "]";
215 break;
216
217 default:
218 dprintk("%s: unsupported address family: %u\n",
219 __func__, da->da_addr.ss_family);
220 goto out_free_da;
221 }
222
223 if (nlen != match_netid_len || strncmp(netid, match_netid, nlen)) {
224 dprintk("%s: ERROR: r_netid \"%s\" != \"%s\"\n",
225 __func__, netid, match_netid);
226 goto out_free_da;
227 }
228
229 /* save human readable address */
230 len = strlen(startsep) + strlen(buf) + strlen(endsep) + 7;
231 da->da_remotestr = kzalloc(len, gfp_flags);
232
233 /* NULL is ok, only used for dprintk */
234 if (da->da_remotestr)
235 snprintf(da->da_remotestr, len, "%s%s%s:%u", startsep,
236 buf, endsep, ntohs(port));
237
238 dprintk("%s: Parsed DS addr %s\n", __func__, da->da_remotestr);
239 kfree(buf);
240 kfree(netid);
241 return da;
242
243out_free_da:
244 kfree(da);
245out_free_buf:
246 dprintk("%s: Error parsing DS addr: %s\n", __func__, buf);
247 kfree(buf);
248out_free_netid:
249 kfree(netid);
250out_err:
251 return NULL;
252}
253
254/* Decode opaque device data and return the result */ 106/* Decode opaque device data and return the result */
255struct nfs4_file_layout_dsaddr * 107struct nfs4_file_layout_dsaddr *
256nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, 108nfs4_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,
353 205
354 mp_count = be32_to_cpup(p); /* multipath count */ 206 mp_count = be32_to_cpup(p); /* multipath count */
355 for (j = 0; j < mp_count; j++) { 207 for (j = 0; j < mp_count; j++) {
356 da = decode_ds_addr(server->nfs_client->cl_net, 208 da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
357 &stream, gfp_flags); 209 &stream, gfp_flags);
358 if (da) 210 if (da)
359 list_add_tail(&da->da_node, &dsaddrs); 211 list_add_tail(&da->da_node, &dsaddrs);
360 } 212 }