diff options
Diffstat (limited to 'fs/nfs/dns_resolve.c')
-rw-r--r-- | fs/nfs/dns_resolve.c | 130 |
1 files changed, 103 insertions, 27 deletions
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index a6e711ad130f..b3924b8a6000 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c | |||
@@ -10,8 +10,9 @@ | |||
10 | 10 | ||
11 | #include <linux/sunrpc/clnt.h> | 11 | #include <linux/sunrpc/clnt.h> |
12 | #include <linux/dns_resolver.h> | 12 | #include <linux/dns_resolver.h> |
13 | #include "dns_resolve.h" | ||
13 | 14 | ||
14 | ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | 15 | ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen, |
15 | struct sockaddr *sa, size_t salen) | 16 | struct sockaddr *sa, size_t salen) |
16 | { | 17 | { |
17 | ssize_t ret; | 18 | ssize_t ret; |
@@ -20,7 +21,7 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | |||
20 | 21 | ||
21 | ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL); | 22 | ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL); |
22 | if (ip_len > 0) | 23 | if (ip_len > 0) |
23 | ret = rpc_pton(ip_addr, ip_len, sa, salen); | 24 | ret = rpc_pton(net, ip_addr, ip_len, sa, salen); |
24 | else | 25 | else |
25 | ret = -ESRCH; | 26 | ret = -ESRCH; |
26 | kfree(ip_addr); | 27 | kfree(ip_addr); |
@@ -40,15 +41,15 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | |||
40 | #include <linux/sunrpc/clnt.h> | 41 | #include <linux/sunrpc/clnt.h> |
41 | #include <linux/sunrpc/cache.h> | 42 | #include <linux/sunrpc/cache.h> |
42 | #include <linux/sunrpc/svcauth.h> | 43 | #include <linux/sunrpc/svcauth.h> |
44 | #include <linux/sunrpc/rpc_pipe_fs.h> | ||
43 | 45 | ||
44 | #include "dns_resolve.h" | 46 | #include "dns_resolve.h" |
45 | #include "cache_lib.h" | 47 | #include "cache_lib.h" |
48 | #include "netns.h" | ||
46 | 49 | ||
47 | #define NFS_DNS_HASHBITS 4 | 50 | #define NFS_DNS_HASHBITS 4 |
48 | #define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS) | 51 | #define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS) |
49 | 52 | ||
50 | static struct cache_head *nfs_dns_table[NFS_DNS_HASHTBL_SIZE]; | ||
51 | |||
52 | struct nfs_dns_ent { | 53 | struct nfs_dns_ent { |
53 | struct cache_head h; | 54 | struct cache_head h; |
54 | 55 | ||
@@ -224,7 +225,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) | |||
224 | len = qword_get(&buf, buf1, sizeof(buf1)); | 225 | len = qword_get(&buf, buf1, sizeof(buf1)); |
225 | if (len <= 0) | 226 | if (len <= 0) |
226 | goto out; | 227 | goto out; |
227 | key.addrlen = rpc_pton(buf1, len, | 228 | key.addrlen = rpc_pton(cd->net, buf1, len, |
228 | (struct sockaddr *)&key.addr, | 229 | (struct sockaddr *)&key.addr, |
229 | sizeof(key.addr)); | 230 | sizeof(key.addr)); |
230 | 231 | ||
@@ -259,21 +260,6 @@ out: | |||
259 | return ret; | 260 | return ret; |
260 | } | 261 | } |
261 | 262 | ||
262 | static struct cache_detail nfs_dns_resolve = { | ||
263 | .owner = THIS_MODULE, | ||
264 | .hash_size = NFS_DNS_HASHTBL_SIZE, | ||
265 | .hash_table = nfs_dns_table, | ||
266 | .name = "dns_resolve", | ||
267 | .cache_put = nfs_dns_ent_put, | ||
268 | .cache_upcall = nfs_dns_upcall, | ||
269 | .cache_parse = nfs_dns_parse, | ||
270 | .cache_show = nfs_dns_show, | ||
271 | .match = nfs_dns_match, | ||
272 | .init = nfs_dns_ent_init, | ||
273 | .update = nfs_dns_ent_update, | ||
274 | .alloc = nfs_dns_ent_alloc, | ||
275 | }; | ||
276 | |||
277 | static int do_cache_lookup(struct cache_detail *cd, | 263 | static int do_cache_lookup(struct cache_detail *cd, |
278 | struct nfs_dns_ent *key, | 264 | struct nfs_dns_ent *key, |
279 | struct nfs_dns_ent **item, | 265 | struct nfs_dns_ent **item, |
@@ -336,8 +322,8 @@ out: | |||
336 | return ret; | 322 | return ret; |
337 | } | 323 | } |
338 | 324 | ||
339 | ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | 325 | ssize_t nfs_dns_resolve_name(struct net *net, char *name, |
340 | struct sockaddr *sa, size_t salen) | 326 | size_t namelen, struct sockaddr *sa, size_t salen) |
341 | { | 327 | { |
342 | struct nfs_dns_ent key = { | 328 | struct nfs_dns_ent key = { |
343 | .hostname = name, | 329 | .hostname = name, |
@@ -345,28 +331,118 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | |||
345 | }; | 331 | }; |
346 | struct nfs_dns_ent *item = NULL; | 332 | struct nfs_dns_ent *item = NULL; |
347 | ssize_t ret; | 333 | ssize_t ret; |
334 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
348 | 335 | ||
349 | ret = do_cache_lookup_wait(&nfs_dns_resolve, &key, &item); | 336 | ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item); |
350 | if (ret == 0) { | 337 | if (ret == 0) { |
351 | if (salen >= item->addrlen) { | 338 | if (salen >= item->addrlen) { |
352 | memcpy(sa, &item->addr, item->addrlen); | 339 | memcpy(sa, &item->addr, item->addrlen); |
353 | ret = item->addrlen; | 340 | ret = item->addrlen; |
354 | } else | 341 | } else |
355 | ret = -EOVERFLOW; | 342 | ret = -EOVERFLOW; |
356 | cache_put(&item->h, &nfs_dns_resolve); | 343 | cache_put(&item->h, nn->nfs_dns_resolve); |
357 | } else if (ret == -ENOENT) | 344 | } else if (ret == -ENOENT) |
358 | ret = -ESRCH; | 345 | ret = -ESRCH; |
359 | return ret; | 346 | return ret; |
360 | } | 347 | } |
361 | 348 | ||
349 | int nfs_dns_resolver_cache_init(struct net *net) | ||
350 | { | ||
351 | int err = -ENOMEM; | ||
352 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
353 | struct cache_detail *cd; | ||
354 | struct cache_head **tbl; | ||
355 | |||
356 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | ||
357 | if (cd == NULL) | ||
358 | goto err_cd; | ||
359 | |||
360 | tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *), | ||
361 | GFP_KERNEL); | ||
362 | if (tbl == NULL) | ||
363 | goto err_tbl; | ||
364 | |||
365 | cd->owner = THIS_MODULE, | ||
366 | cd->hash_size = NFS_DNS_HASHTBL_SIZE, | ||
367 | cd->hash_table = tbl, | ||
368 | cd->name = "dns_resolve", | ||
369 | cd->cache_put = nfs_dns_ent_put, | ||
370 | cd->cache_upcall = nfs_dns_upcall, | ||
371 | cd->cache_parse = nfs_dns_parse, | ||
372 | cd->cache_show = nfs_dns_show, | ||
373 | cd->match = nfs_dns_match, | ||
374 | cd->init = nfs_dns_ent_init, | ||
375 | cd->update = nfs_dns_ent_update, | ||
376 | cd->alloc = nfs_dns_ent_alloc, | ||
377 | |||
378 | nfs_cache_init(cd); | ||
379 | err = nfs_cache_register_net(net, cd); | ||
380 | if (err) | ||
381 | goto err_reg; | ||
382 | nn->nfs_dns_resolve = cd; | ||
383 | return 0; | ||
384 | |||
385 | err_reg: | ||
386 | nfs_cache_destroy(cd); | ||
387 | kfree(cd->hash_table); | ||
388 | err_tbl: | ||
389 | kfree(cd); | ||
390 | err_cd: | ||
391 | return err; | ||
392 | } | ||
393 | |||
394 | void nfs_dns_resolver_cache_destroy(struct net *net) | ||
395 | { | ||
396 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
397 | struct cache_detail *cd = nn->nfs_dns_resolve; | ||
398 | |||
399 | nfs_cache_unregister_net(net, cd); | ||
400 | nfs_cache_destroy(cd); | ||
401 | kfree(cd->hash_table); | ||
402 | kfree(cd); | ||
403 | } | ||
404 | |||
405 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | ||
406 | void *ptr) | ||
407 | { | ||
408 | struct super_block *sb = ptr; | ||
409 | struct net *net = sb->s_fs_info; | ||
410 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
411 | struct cache_detail *cd = nn->nfs_dns_resolve; | ||
412 | int ret = 0; | ||
413 | |||
414 | if (cd == NULL) | ||
415 | return 0; | ||
416 | |||
417 | if (!try_module_get(THIS_MODULE)) | ||
418 | return 0; | ||
419 | |||
420 | switch (event) { | ||
421 | case RPC_PIPEFS_MOUNT: | ||
422 | ret = nfs_cache_register_sb(sb, cd); | ||
423 | break; | ||
424 | case RPC_PIPEFS_UMOUNT: | ||
425 | nfs_cache_unregister_sb(sb, cd); | ||
426 | break; | ||
427 | default: | ||
428 | ret = -ENOTSUPP; | ||
429 | break; | ||
430 | } | ||
431 | module_put(THIS_MODULE); | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | static struct notifier_block nfs_dns_resolver_block = { | ||
436 | .notifier_call = rpc_pipefs_event, | ||
437 | }; | ||
438 | |||
362 | int nfs_dns_resolver_init(void) | 439 | int nfs_dns_resolver_init(void) |
363 | { | 440 | { |
364 | return nfs_cache_register(&nfs_dns_resolve); | 441 | return rpc_pipefs_notifier_register(&nfs_dns_resolver_block); |
365 | } | 442 | } |
366 | 443 | ||
367 | void nfs_dns_resolver_destroy(void) | 444 | void nfs_dns_resolver_destroy(void) |
368 | { | 445 | { |
369 | nfs_cache_unregister(&nfs_dns_resolve); | 446 | rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); |
370 | } | 447 | } |
371 | |||
372 | #endif | 448 | #endif |