aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2011-11-25 09:13:04 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 18:20:26 -0500
commit1b340d0118da1d7c60c664f17d7c8fce2bb1cd9d (patch)
treea66a9626f8fca21bd42d13a3b4270b168e2186fc
parent5c1cacb175185ed925d7dc13ac7e0653e7a633cd (diff)
NFS: DNS resolver cache per network namespace context introduced
This patch implements DNS resolver cache creation and registration for each alive network namespace context. This was done by registering NFS per-net operations, responsible for DNS cache allocation/register and unregister/destructioning instead of initialization and destruction of static "nfs_dns_resolve" cache detail (this one was removed). Pointer to network dns resolver cache is stored in new per-net "nfs_net" structure. This patch also changes nfs_dns_resolve_name() function prototype (and it's calls) by adding network pointer parameter, which is used to get proper DNS resolver cache pointer for do_cache_lookup_wait() call. Note: empty nfs_dns_resolver_init() and nfs_dns_resolver_destroy() functions will be used in next patch in the series. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/dns_resolve.c96
-rw-r--r--fs/nfs/dns_resolve.h14
-rw-r--r--fs/nfs/inode.c33
-rw-r--r--fs/nfs/netns.h13
-rw-r--r--fs/nfs/nfs4namespace.c8
5 files changed, 123 insertions, 41 deletions
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index 3cbf4b88f827..9aea78ab86ac 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -11,7 +11,7 @@
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 13
14ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 14ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
15 struct sockaddr *sa, size_t salen) 15 struct sockaddr *sa, size_t salen)
16{ 16{
17 ssize_t ret; 17 ssize_t ret;
@@ -43,12 +43,11 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
43 43
44#include "dns_resolve.h" 44#include "dns_resolve.h"
45#include "cache_lib.h" 45#include "cache_lib.h"
46#include "netns.h"
46 47
47#define NFS_DNS_HASHBITS 4 48#define NFS_DNS_HASHBITS 4
48#define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS) 49#define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS)
49 50
50static struct cache_head *nfs_dns_table[NFS_DNS_HASHTBL_SIZE];
51
52struct nfs_dns_ent { 51struct nfs_dns_ent {
53 struct cache_head h; 52 struct cache_head h;
54 53
@@ -259,21 +258,6 @@ out:
259 return ret; 258 return ret;
260} 259}
261 260
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, 261static int do_cache_lookup(struct cache_detail *cd,
278 struct nfs_dns_ent *key, 262 struct nfs_dns_ent *key,
279 struct nfs_dns_ent **item, 263 struct nfs_dns_ent **item,
@@ -336,8 +320,8 @@ out:
336 return ret; 320 return ret;
337} 321}
338 322
339ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 323ssize_t nfs_dns_resolve_name(struct net *net, char *name,
340 struct sockaddr *sa, size_t salen) 324 size_t namelen, struct sockaddr *sa, size_t salen)
341{ 325{
342 struct nfs_dns_ent key = { 326 struct nfs_dns_ent key = {
343 .hostname = name, 327 .hostname = name,
@@ -345,37 +329,83 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
345 }; 329 };
346 struct nfs_dns_ent *item = NULL; 330 struct nfs_dns_ent *item = NULL;
347 ssize_t ret; 331 ssize_t ret;
332 struct nfs_net *nn = net_generic(net, nfs_net_id);
348 333
349 ret = do_cache_lookup_wait(&nfs_dns_resolve, &key, &item); 334 ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item);
350 if (ret == 0) { 335 if (ret == 0) {
351 if (salen >= item->addrlen) { 336 if (salen >= item->addrlen) {
352 memcpy(sa, &item->addr, item->addrlen); 337 memcpy(sa, &item->addr, item->addrlen);
353 ret = item->addrlen; 338 ret = item->addrlen;
354 } else 339 } else
355 ret = -EOVERFLOW; 340 ret = -EOVERFLOW;
356 cache_put(&item->h, &nfs_dns_resolve); 341 cache_put(&item->h, nn->nfs_dns_resolve);
357 } else if (ret == -ENOENT) 342 } else if (ret == -ENOENT)
358 ret = -ESRCH; 343 ret = -ESRCH;
359 return ret; 344 return ret;
360} 345}
361 346
362int nfs_dns_resolver_init(void) 347int nfs_dns_resolver_cache_init(struct net *net)
363{ 348{
364 int err; 349 int err = -ENOMEM;
350 struct nfs_net *nn = net_generic(net, nfs_net_id);
351 struct cache_detail *cd;
352 struct cache_head **tbl;
353
354 cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
355 if (cd == NULL)
356 goto err_cd;
357
358 tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *),
359 GFP_KERNEL);
360 if (tbl == NULL)
361 goto err_tbl;
362
363 cd->owner = THIS_MODULE,
364 cd->hash_size = NFS_DNS_HASHTBL_SIZE,
365 cd->hash_table = tbl,
366 cd->name = "dns_resolve",
367 cd->cache_put = nfs_dns_ent_put,
368 cd->cache_upcall = nfs_dns_upcall,
369 cd->cache_parse = nfs_dns_parse,
370 cd->cache_show = nfs_dns_show,
371 cd->match = nfs_dns_match,
372 cd->init = nfs_dns_ent_init,
373 cd->update = nfs_dns_ent_update,
374 cd->alloc = nfs_dns_ent_alloc,
375
376 nfs_cache_init(cd);
377 err = nfs_cache_register_net(net, cd);
378 if (err)
379 goto err_reg;
380 nn->nfs_dns_resolve = cd;
381 return 0;
365 382
366 nfs_cache_init(&nfs_dns_resolve); 383err_reg:
367 err = nfs_cache_register_net(&init_net, &nfs_dns_resolve); 384 nfs_cache_destroy(cd);
368 if (err) { 385 kfree(cd->hash_table);
369 nfs_cache_destroy(&nfs_dns_resolve); 386err_tbl:
370 return err; 387 kfree(cd);
371 } 388err_cd:
389 return err;
390}
391
392void nfs_dns_resolver_cache_destroy(struct net *net)
393{
394 struct nfs_net *nn = net_generic(net, nfs_net_id);
395 struct cache_detail *cd = nn->nfs_dns_resolve;
396
397 nfs_cache_unregister_net(net, cd);
398 nfs_cache_destroy(cd);
399 kfree(cd->hash_table);
400 kfree(cd);
401}
402
403int nfs_dns_resolver_init(void)
404{
372 return 0; 405 return 0;
373} 406}
374 407
375void nfs_dns_resolver_destroy(void) 408void nfs_dns_resolver_destroy(void)
376{ 409{
377 nfs_cache_unregister_net(&init_net, &nfs_dns_resolve);
378 nfs_cache_destroy(&nfs_dns_resolve);
379} 410}
380
381#endif 411#endif
diff --git a/fs/nfs/dns_resolve.h b/fs/nfs/dns_resolve.h
index 199bb5543a91..2e4f596d2923 100644
--- a/fs/nfs/dns_resolve.h
+++ b/fs/nfs/dns_resolve.h
@@ -15,12 +15,22 @@ static inline int nfs_dns_resolver_init(void)
15 15
16static inline void nfs_dns_resolver_destroy(void) 16static inline void nfs_dns_resolver_destroy(void)
17{} 17{}
18
19static inline int nfs_dns_resolver_cache_init(struct net *net)
20{
21 return 0;
22}
23
24static inline void nfs_dns_resolver_cache_destroy(struct net *net)
25{}
18#else 26#else
19extern int nfs_dns_resolver_init(void); 27extern int nfs_dns_resolver_init(void);
20extern void nfs_dns_resolver_destroy(void); 28extern void nfs_dns_resolver_destroy(void);
29extern int nfs_dns_resolver_cache_init(struct net *net);
30extern void nfs_dns_resolver_cache_destroy(struct net *net);
21#endif 31#endif
22 32
23extern ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 33extern ssize_t nfs_dns_resolve_name(struct net *net, char *name,
24 struct sockaddr *sa, size_t salen); 34 size_t namelen, struct sockaddr *sa, size_t salen);
25 35
26#endif 36#endif
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f649fba8c384..0335f6e4ff7e 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -51,6 +51,7 @@
51#include "fscache.h" 51#include "fscache.h"
52#include "dns_resolve.h" 52#include "dns_resolve.h"
53#include "pnfs.h" 53#include "pnfs.h"
54#include "netns.h"
54 55
55#define NFSDBG_FACILITY NFSDBG_VFS 56#define NFSDBG_FACILITY NFSDBG_VFS
56 57
@@ -1552,6 +1553,25 @@ static void nfsiod_stop(void)
1552 destroy_workqueue(wq); 1553 destroy_workqueue(wq);
1553} 1554}
1554 1555
1556int nfs_net_id;
1557
1558static int nfs_net_init(struct net *net)
1559{
1560 return nfs_dns_resolver_cache_init(net);
1561}
1562
1563static void nfs_net_exit(struct net *net)
1564{
1565 nfs_dns_resolver_cache_destroy(net);
1566}
1567
1568static struct pernet_operations nfs_net_ops = {
1569 .init = nfs_net_init,
1570 .exit = nfs_net_exit,
1571 .id = &nfs_net_id,
1572 .size = sizeof(struct nfs_net),
1573};
1574
1555/* 1575/*
1556 * Initialize NFS 1576 * Initialize NFS
1557 */ 1577 */
@@ -1561,10 +1581,14 @@ static int __init init_nfs_fs(void)
1561 1581
1562 err = nfs_idmap_init(); 1582 err = nfs_idmap_init();
1563 if (err < 0) 1583 if (err < 0)
1564 goto out9; 1584 goto out10;
1565 1585
1566 err = nfs_dns_resolver_init(); 1586 err = nfs_dns_resolver_init();
1567 if (err < 0) 1587 if (err < 0)
1588 goto out9;
1589
1590 err = register_pernet_subsys(&nfs_net_ops);
1591 if (err < 0)
1568 goto out8; 1592 goto out8;
1569 1593
1570 err = nfs_fscache_register(); 1594 err = nfs_fscache_register();
@@ -1625,10 +1649,12 @@ out5:
1625out6: 1649out6:
1626 nfs_fscache_unregister(); 1650 nfs_fscache_unregister();
1627out7: 1651out7:
1628 nfs_dns_resolver_destroy(); 1652 unregister_pernet_subsys(&nfs_net_ops);
1629out8: 1653out8:
1630 nfs_idmap_quit(); 1654 nfs_dns_resolver_destroy();
1631out9: 1655out9:
1656 nfs_idmap_quit();
1657out10:
1632 return err; 1658 return err;
1633} 1659}
1634 1660
@@ -1640,6 +1666,7 @@ static void __exit exit_nfs_fs(void)
1640 nfs_destroy_inodecache(); 1666 nfs_destroy_inodecache();
1641 nfs_destroy_nfspagecache(); 1667 nfs_destroy_nfspagecache();
1642 nfs_fscache_unregister(); 1668 nfs_fscache_unregister();
1669 unregister_pernet_subsys(&nfs_net_ops);
1643 nfs_dns_resolver_destroy(); 1670 nfs_dns_resolver_destroy();
1644 nfs_idmap_quit(); 1671 nfs_idmap_quit();
1645#ifdef CONFIG_PROC_FS 1672#ifdef CONFIG_PROC_FS
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h
new file mode 100644
index 000000000000..8c1f130d6ca2
--- /dev/null
+++ b/fs/nfs/netns.h
@@ -0,0 +1,13 @@
1#ifndef __NFS_NETNS_H__
2#define __NFS_NETNS_H__
3
4#include <net/net_namespace.h>
5#include <net/netns/generic.h>
6
7struct nfs_net {
8 struct cache_detail *nfs_dns_resolve;
9};
10
11extern int nfs_net_id;
12
13#endif
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index bb80c49b6533..919a36935924 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -94,13 +94,14 @@ static int nfs4_validate_fspath(struct dentry *dentry,
94} 94}
95 95
96static size_t nfs_parse_server_name(char *string, size_t len, 96static size_t nfs_parse_server_name(char *string, size_t len,
97 struct sockaddr *sa, size_t salen) 97 struct sockaddr *sa, size_t salen, struct nfs_server *server)
98{ 98{
99 ssize_t ret; 99 ssize_t ret;
100 100
101 ret = rpc_pton(string, len, sa, salen); 101 ret = rpc_pton(string, len, sa, salen);
102 if (ret == 0) { 102 if (ret == 0) {
103 ret = nfs_dns_resolve_name(string, len, sa, salen); 103 ret = nfs_dns_resolve_name(server->client->cl_xprt->xprt_net,
104 string, len, sa, salen);
104 if (ret < 0) 105 if (ret < 0)
105 ret = 0; 106 ret = 0;
106 } 107 }
@@ -137,7 +138,8 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
137 continue; 138 continue;
138 139
139 mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, 140 mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
140 mountdata->addr, addr_bufsize); 141 mountdata->addr, addr_bufsize,
142 NFS_SB(mountdata->sb));
141 if (mountdata->addrlen == 0) 143 if (mountdata->addrlen == 0)
142 continue; 144 continue;
143 145