diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2011-11-25 09:13:04 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-31 18:20:26 -0500 |
commit | 1b340d0118da1d7c60c664f17d7c8fce2bb1cd9d (patch) | |
tree | a66a9626f8fca21bd42d13a3b4270b168e2186fc | |
parent | 5c1cacb175185ed925d7dc13ac7e0653e7a633cd (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.c | 96 | ||||
-rw-r--r-- | fs/nfs/dns_resolve.h | 14 | ||||
-rw-r--r-- | fs/nfs/inode.c | 33 | ||||
-rw-r--r-- | fs/nfs/netns.h | 13 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 8 |
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 | ||
14 | ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | 14 | ssize_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 | ||
50 | static struct cache_head *nfs_dns_table[NFS_DNS_HASHTBL_SIZE]; | ||
51 | |||
52 | struct nfs_dns_ent { | 51 | struct 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 | ||
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, | 261 | static 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 | ||
339 | ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | 323 | ssize_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 | ||
362 | int nfs_dns_resolver_init(void) | 347 | int 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); | 383 | err_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); | 386 | err_tbl: |
370 | return err; | 387 | kfree(cd); |
371 | } | 388 | err_cd: |
389 | return err; | ||
390 | } | ||
391 | |||
392 | void 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 | |||
403 | int nfs_dns_resolver_init(void) | ||
404 | { | ||
372 | return 0; | 405 | return 0; |
373 | } | 406 | } |
374 | 407 | ||
375 | void nfs_dns_resolver_destroy(void) | 408 | void 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 | ||
16 | static inline void nfs_dns_resolver_destroy(void) | 16 | static inline void nfs_dns_resolver_destroy(void) |
17 | {} | 17 | {} |
18 | |||
19 | static inline int nfs_dns_resolver_cache_init(struct net *net) | ||
20 | { | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | static inline void nfs_dns_resolver_cache_destroy(struct net *net) | ||
25 | {} | ||
18 | #else | 26 | #else |
19 | extern int nfs_dns_resolver_init(void); | 27 | extern int nfs_dns_resolver_init(void); |
20 | extern void nfs_dns_resolver_destroy(void); | 28 | extern void nfs_dns_resolver_destroy(void); |
29 | extern int nfs_dns_resolver_cache_init(struct net *net); | ||
30 | extern void nfs_dns_resolver_cache_destroy(struct net *net); | ||
21 | #endif | 31 | #endif |
22 | 32 | ||
23 | extern ssize_t nfs_dns_resolve_name(char *name, size_t namelen, | 33 | extern 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 | ||
1556 | int nfs_net_id; | ||
1557 | |||
1558 | static int nfs_net_init(struct net *net) | ||
1559 | { | ||
1560 | return nfs_dns_resolver_cache_init(net); | ||
1561 | } | ||
1562 | |||
1563 | static void nfs_net_exit(struct net *net) | ||
1564 | { | ||
1565 | nfs_dns_resolver_cache_destroy(net); | ||
1566 | } | ||
1567 | |||
1568 | static 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: | |||
1625 | out6: | 1649 | out6: |
1626 | nfs_fscache_unregister(); | 1650 | nfs_fscache_unregister(); |
1627 | out7: | 1651 | out7: |
1628 | nfs_dns_resolver_destroy(); | 1652 | unregister_pernet_subsys(&nfs_net_ops); |
1629 | out8: | 1653 | out8: |
1630 | nfs_idmap_quit(); | 1654 | nfs_dns_resolver_destroy(); |
1631 | out9: | 1655 | out9: |
1656 | nfs_idmap_quit(); | ||
1657 | out10: | ||
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 | |||
7 | struct nfs_net { | ||
8 | struct cache_detail *nfs_dns_resolve; | ||
9 | }; | ||
10 | |||
11 | extern 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 | ||
96 | static size_t nfs_parse_server_name(char *string, size_t len, | 96 | static 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 | ||