Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stanislav Kinsbursky and committed by
Trond Myklebust
1b340d01 5c1cacb1

+123 -41
+63 -33
fs/nfs/dns_resolve.c
··· 11 11 #include <linux/sunrpc/clnt.h> 12 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 15 struct sockaddr *sa, size_t salen) 16 16 { 17 17 ssize_t ret; ··· 43 43 44 44 #include "dns_resolve.h" 45 45 #include "cache_lib.h" 46 + #include "netns.h" 46 47 47 48 #define NFS_DNS_HASHBITS 4 48 49 #define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS) 49 - 50 - static struct cache_head *nfs_dns_table[NFS_DNS_HASHTBL_SIZE]; 51 50 52 51 struct nfs_dns_ent { 53 52 struct cache_head h; ··· 258 259 return ret; 259 260 } 260 261 261 - static struct cache_detail nfs_dns_resolve = { 262 - .owner = THIS_MODULE, 263 - .hash_size = NFS_DNS_HASHTBL_SIZE, 264 - .hash_table = nfs_dns_table, 265 - .name = "dns_resolve", 266 - .cache_put = nfs_dns_ent_put, 267 - .cache_upcall = nfs_dns_upcall, 268 - .cache_parse = nfs_dns_parse, 269 - .cache_show = nfs_dns_show, 270 - .match = nfs_dns_match, 271 - .init = nfs_dns_ent_init, 272 - .update = nfs_dns_ent_update, 273 - .alloc = nfs_dns_ent_alloc, 274 - }; 275 - 276 262 static int do_cache_lookup(struct cache_detail *cd, 277 263 struct nfs_dns_ent *key, 278 264 struct nfs_dns_ent **item, ··· 320 336 return ret; 321 337 } 322 338 323 - ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 324 - struct sockaddr *sa, size_t salen) 339 + ssize_t nfs_dns_resolve_name(struct net *net, char *name, 340 + size_t namelen, struct sockaddr *sa, size_t salen) 325 341 { 326 342 struct nfs_dns_ent key = { 327 343 .hostname = name, ··· 329 345 }; 330 346 struct nfs_dns_ent *item = NULL; 331 347 ssize_t ret; 348 + struct nfs_net *nn = net_generic(net, nfs_net_id); 332 349 333 - ret = do_cache_lookup_wait(&nfs_dns_resolve, &key, &item); 350 + ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item); 334 351 if (ret == 0) { 335 352 if (salen >= item->addrlen) { 336 353 memcpy(sa, &item->addr, item->addrlen); 337 354 ret = item->addrlen; 338 355 } else 339 356 ret = -EOVERFLOW; 340 - cache_put(&item->h, &nfs_dns_resolve); 357 + cache_put(&item->h, nn->nfs_dns_resolve); 341 358 } else if (ret == -ENOENT) 342 359 ret = -ESRCH; 343 360 return ret; 344 361 } 345 362 363 + int nfs_dns_resolver_cache_init(struct net *net) 364 + { 365 + int err = -ENOMEM; 366 + struct nfs_net *nn = net_generic(net, nfs_net_id); 367 + struct cache_detail *cd; 368 + struct cache_head **tbl; 369 + 370 + cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); 371 + if (cd == NULL) 372 + goto err_cd; 373 + 374 + tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *), 375 + GFP_KERNEL); 376 + if (tbl == NULL) 377 + goto err_tbl; 378 + 379 + cd->owner = THIS_MODULE, 380 + cd->hash_size = NFS_DNS_HASHTBL_SIZE, 381 + cd->hash_table = tbl, 382 + cd->name = "dns_resolve", 383 + cd->cache_put = nfs_dns_ent_put, 384 + cd->cache_upcall = nfs_dns_upcall, 385 + cd->cache_parse = nfs_dns_parse, 386 + cd->cache_show = nfs_dns_show, 387 + cd->match = nfs_dns_match, 388 + cd->init = nfs_dns_ent_init, 389 + cd->update = nfs_dns_ent_update, 390 + cd->alloc = nfs_dns_ent_alloc, 391 + 392 + nfs_cache_init(cd); 393 + err = nfs_cache_register_net(net, cd); 394 + if (err) 395 + goto err_reg; 396 + nn->nfs_dns_resolve = cd; 397 + return 0; 398 + 399 + err_reg: 400 + nfs_cache_destroy(cd); 401 + kfree(cd->hash_table); 402 + err_tbl: 403 + kfree(cd); 404 + err_cd: 405 + return err; 406 + } 407 + 408 + void nfs_dns_resolver_cache_destroy(struct net *net) 409 + { 410 + struct nfs_net *nn = net_generic(net, nfs_net_id); 411 + struct cache_detail *cd = nn->nfs_dns_resolve; 412 + 413 + nfs_cache_unregister_net(net, cd); 414 + nfs_cache_destroy(cd); 415 + kfree(cd->hash_table); 416 + kfree(cd); 417 + } 418 + 346 419 int nfs_dns_resolver_init(void) 347 420 { 348 - int err; 349 - 350 - nfs_cache_init(&nfs_dns_resolve); 351 - err = nfs_cache_register_net(&init_net, &nfs_dns_resolve); 352 - if (err) { 353 - nfs_cache_destroy(&nfs_dns_resolve); 354 - return err; 355 - } 356 421 return 0; 357 422 } 358 423 359 424 void nfs_dns_resolver_destroy(void) 360 425 { 361 - nfs_cache_unregister_net(&init_net, &nfs_dns_resolve); 362 - nfs_cache_destroy(&nfs_dns_resolve); 363 426 } 364 - 365 427 #endif
+12 -2
fs/nfs/dns_resolve.h
··· 15 15 16 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 26 #else 19 27 extern int nfs_dns_resolver_init(void); 20 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 31 #endif 22 32 23 - extern ssize_t nfs_dns_resolve_name(char *name, size_t namelen, 24 - struct sockaddr *sa, size_t salen); 33 + extern ssize_t nfs_dns_resolve_name(struct net *net, char *name, 34 + size_t namelen, struct sockaddr *sa, size_t salen); 25 35 26 36 #endif
+30 -3
fs/nfs/inode.c
··· 51 51 #include "fscache.h" 52 52 #include "dns_resolve.h" 53 53 #include "pnfs.h" 54 + #include "netns.h" 54 55 55 56 #define NFSDBG_FACILITY NFSDBG_VFS 56 57 ··· 1553 1552 destroy_workqueue(wq); 1554 1553 } 1555 1554 1555 + int nfs_net_id; 1556 + 1557 + static int nfs_net_init(struct net *net) 1558 + { 1559 + return nfs_dns_resolver_cache_init(net); 1560 + } 1561 + 1562 + static void nfs_net_exit(struct net *net) 1563 + { 1564 + nfs_dns_resolver_cache_destroy(net); 1565 + } 1566 + 1567 + static struct pernet_operations nfs_net_ops = { 1568 + .init = nfs_net_init, 1569 + .exit = nfs_net_exit, 1570 + .id = &nfs_net_id, 1571 + .size = sizeof(struct nfs_net), 1572 + }; 1573 + 1556 1574 /* 1557 1575 * Initialize NFS 1558 1576 */ ··· 1581 1561 1582 1562 err = nfs_idmap_init(); 1583 1563 if (err < 0) 1584 - goto out9; 1564 + goto out10; 1585 1565 1586 1566 err = nfs_dns_resolver_init(); 1567 + if (err < 0) 1568 + goto out9; 1569 + 1570 + err = register_pernet_subsys(&nfs_net_ops); 1587 1571 if (err < 0) 1588 1572 goto out8; 1589 1573 ··· 1649 1625 out6: 1650 1626 nfs_fscache_unregister(); 1651 1627 out7: 1652 - nfs_dns_resolver_destroy(); 1628 + unregister_pernet_subsys(&nfs_net_ops); 1653 1629 out8: 1654 - nfs_idmap_quit(); 1630 + nfs_dns_resolver_destroy(); 1655 1631 out9: 1632 + nfs_idmap_quit(); 1633 + out10: 1656 1634 return err; 1657 1635 } 1658 1636 ··· 1666 1640 nfs_destroy_inodecache(); 1667 1641 nfs_destroy_nfspagecache(); 1668 1642 nfs_fscache_unregister(); 1643 + unregister_pernet_subsys(&nfs_net_ops); 1669 1644 nfs_dns_resolver_destroy(); 1670 1645 nfs_idmap_quit(); 1671 1646 #ifdef CONFIG_PROC_FS
+13
fs/nfs/netns.h
··· 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
+5 -3
fs/nfs/nfs4namespace.c
··· 94 94 } 95 95 96 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 99 ssize_t ret; 100 100 101 101 ret = rpc_pton(string, len, sa, salen); 102 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 105 if (ret < 0) 105 106 ret = 0; 106 107 } ··· 138 137 continue; 139 138 140 139 mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, 141 - mountdata->addr, addr_bufsize); 140 + mountdata->addr, addr_bufsize, 141 + NFS_SB(mountdata->sb)); 142 142 if (mountdata->addrlen == 0) 143 143 continue; 144 144