aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dns_resolve.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/dns_resolve.c')
-rw-r--r--fs/nfs/dns_resolve.c130
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
14ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 15ssize_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
50static struct cache_head *nfs_dns_table[NFS_DNS_HASHTBL_SIZE];
51
52struct nfs_dns_ent { 53struct 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
262static 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
277static int do_cache_lookup(struct cache_detail *cd, 263static 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
339ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 325ssize_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
349int 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
385err_reg:
386 nfs_cache_destroy(cd);
387 kfree(cd->hash_table);
388err_tbl:
389 kfree(cd);
390err_cd:
391 return err;
392}
393
394void 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
405static 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
435static struct notifier_block nfs_dns_resolver_block = {
436 .notifier_call = rpc_pipefs_event,
437};
438
362int nfs_dns_resolver_init(void) 439int 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
367void nfs_dns_resolver_destroy(void) 444void 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