diff options
author | Peng Tao <tao.peng@primarydata.com> | 2014-05-29 09:06:59 -0400 |
---|---|---|
committer | Tom Haynes <loghyr@primarydata.com> | 2015-02-03 14:06:32 -0500 |
commit | 6b7f3cf96364eaf597940cb5c68a682894829915 (patch) | |
tree | 532e1216ff4e72da9600f5504d862ced8e0fd8db /fs/nfs/filelayout | |
parent | 875ae0694be48f3e3bdddd435b79abf52b680299 (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.c | 152 |
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 | */ | ||
110 | static struct nfs4_pnfs_ds_addr * | ||
111 | decode_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 | |||
243 | out_free_da: | ||
244 | kfree(da); | ||
245 | out_free_buf: | ||
246 | dprintk("%s: Error parsing DS addr: %s\n", __func__, buf); | ||
247 | kfree(buf); | ||
248 | out_free_netid: | ||
249 | kfree(netid); | ||
250 | out_err: | ||
251 | return NULL; | ||
252 | } | ||
253 | |||
254 | /* Decode opaque device data and return the result */ | 106 | /* Decode opaque device data and return the result */ |
255 | struct nfs4_file_layout_dsaddr * | 107 | struct nfs4_file_layout_dsaddr * |
256 | nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, | 108 | 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, | |||
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 | } |