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>
This commit is contained in:
parent
5c1cacb175
commit
1b340d0118
@ -11,7 +11,7 @@
|
|||||||
#include <linux/sunrpc/clnt.h>
|
#include <linux/sunrpc/clnt.h>
|
||||||
#include <linux/dns_resolver.h>
|
#include <linux/dns_resolver.h>
|
||||||
|
|
||||||
ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
|
ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
|
||||||
struct sockaddr *sa, size_t salen)
|
struct sockaddr *sa, size_t salen)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
@ -43,12 +43,11 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
|
|||||||
|
|
||||||
#include "dns_resolve.h"
|
#include "dns_resolve.h"
|
||||||
#include "cache_lib.h"
|
#include "cache_lib.h"
|
||||||
|
#include "netns.h"
|
||||||
|
|
||||||
#define NFS_DNS_HASHBITS 4
|
#define NFS_DNS_HASHBITS 4
|
||||||
#define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS)
|
#define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS)
|
||||||
|
|
||||||
static struct cache_head *nfs_dns_table[NFS_DNS_HASHTBL_SIZE];
|
|
||||||
|
|
||||||
struct nfs_dns_ent {
|
struct nfs_dns_ent {
|
||||||
struct cache_head h;
|
struct cache_head h;
|
||||||
|
|
||||||
@ -259,21 +258,6 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cache_detail nfs_dns_resolve = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.hash_size = NFS_DNS_HASHTBL_SIZE,
|
|
||||||
.hash_table = nfs_dns_table,
|
|
||||||
.name = "dns_resolve",
|
|
||||||
.cache_put = nfs_dns_ent_put,
|
|
||||||
.cache_upcall = nfs_dns_upcall,
|
|
||||||
.cache_parse = nfs_dns_parse,
|
|
||||||
.cache_show = nfs_dns_show,
|
|
||||||
.match = nfs_dns_match,
|
|
||||||
.init = nfs_dns_ent_init,
|
|
||||||
.update = nfs_dns_ent_update,
|
|
||||||
.alloc = nfs_dns_ent_alloc,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int do_cache_lookup(struct cache_detail *cd,
|
static int do_cache_lookup(struct cache_detail *cd,
|
||||||
struct nfs_dns_ent *key,
|
struct nfs_dns_ent *key,
|
||||||
struct nfs_dns_ent **item,
|
struct nfs_dns_ent **item,
|
||||||
@ -336,8 +320,8 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
|
ssize_t nfs_dns_resolve_name(struct net *net, char *name,
|
||||||
struct sockaddr *sa, size_t salen)
|
size_t namelen, struct sockaddr *sa, size_t salen)
|
||||||
{
|
{
|
||||||
struct nfs_dns_ent key = {
|
struct nfs_dns_ent key = {
|
||||||
.hostname = name,
|
.hostname = name,
|
||||||
@ -345,37 +329,83 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
|
|||||||
};
|
};
|
||||||
struct nfs_dns_ent *item = NULL;
|
struct nfs_dns_ent *item = NULL;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
||||||
|
|
||||||
ret = do_cache_lookup_wait(&nfs_dns_resolve, &key, &item);
|
ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
if (salen >= item->addrlen) {
|
if (salen >= item->addrlen) {
|
||||||
memcpy(sa, &item->addr, item->addrlen);
|
memcpy(sa, &item->addr, item->addrlen);
|
||||||
ret = item->addrlen;
|
ret = item->addrlen;
|
||||||
} else
|
} else
|
||||||
ret = -EOVERFLOW;
|
ret = -EOVERFLOW;
|
||||||
cache_put(&item->h, &nfs_dns_resolve);
|
cache_put(&item->h, nn->nfs_dns_resolve);
|
||||||
} else if (ret == -ENOENT)
|
} else if (ret == -ENOENT)
|
||||||
ret = -ESRCH;
|
ret = -ESRCH;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nfs_dns_resolver_cache_init(struct net *net)
|
||||||
|
{
|
||||||
|
int err = -ENOMEM;
|
||||||
|
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
||||||
|
struct cache_detail *cd;
|
||||||
|
struct cache_head **tbl;
|
||||||
|
|
||||||
|
cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
|
||||||
|
if (cd == NULL)
|
||||||
|
goto err_cd;
|
||||||
|
|
||||||
|
tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (tbl == NULL)
|
||||||
|
goto err_tbl;
|
||||||
|
|
||||||
|
cd->owner = THIS_MODULE,
|
||||||
|
cd->hash_size = NFS_DNS_HASHTBL_SIZE,
|
||||||
|
cd->hash_table = tbl,
|
||||||
|
cd->name = "dns_resolve",
|
||||||
|
cd->cache_put = nfs_dns_ent_put,
|
||||||
|
cd->cache_upcall = nfs_dns_upcall,
|
||||||
|
cd->cache_parse = nfs_dns_parse,
|
||||||
|
cd->cache_show = nfs_dns_show,
|
||||||
|
cd->match = nfs_dns_match,
|
||||||
|
cd->init = nfs_dns_ent_init,
|
||||||
|
cd->update = nfs_dns_ent_update,
|
||||||
|
cd->alloc = nfs_dns_ent_alloc,
|
||||||
|
|
||||||
|
nfs_cache_init(cd);
|
||||||
|
err = nfs_cache_register_net(net, cd);
|
||||||
|
if (err)
|
||||||
|
goto err_reg;
|
||||||
|
nn->nfs_dns_resolve = cd;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_reg:
|
||||||
|
nfs_cache_destroy(cd);
|
||||||
|
kfree(cd->hash_table);
|
||||||
|
err_tbl:
|
||||||
|
kfree(cd);
|
||||||
|
err_cd:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfs_dns_resolver_cache_destroy(struct net *net)
|
||||||
|
{
|
||||||
|
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
||||||
|
struct cache_detail *cd = nn->nfs_dns_resolve;
|
||||||
|
|
||||||
|
nfs_cache_unregister_net(net, cd);
|
||||||
|
nfs_cache_destroy(cd);
|
||||||
|
kfree(cd->hash_table);
|
||||||
|
kfree(cd);
|
||||||
|
}
|
||||||
|
|
||||||
int nfs_dns_resolver_init(void)
|
int nfs_dns_resolver_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
|
|
||||||
nfs_cache_init(&nfs_dns_resolve);
|
|
||||||
err = nfs_cache_register_net(&init_net, &nfs_dns_resolve);
|
|
||||||
if (err) {
|
|
||||||
nfs_cache_destroy(&nfs_dns_resolve);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_dns_resolver_destroy(void)
|
void nfs_dns_resolver_destroy(void)
|
||||||
{
|
{
|
||||||
nfs_cache_unregister_net(&init_net, &nfs_dns_resolve);
|
|
||||||
nfs_cache_destroy(&nfs_dns_resolve);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,12 +15,22 @@ static inline int nfs_dns_resolver_init(void)
|
|||||||
|
|
||||||
static inline void nfs_dns_resolver_destroy(void)
|
static inline void nfs_dns_resolver_destroy(void)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
static inline int nfs_dns_resolver_cache_init(struct net *net)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nfs_dns_resolver_cache_destroy(struct net *net)
|
||||||
|
{}
|
||||||
#else
|
#else
|
||||||
extern int nfs_dns_resolver_init(void);
|
extern int nfs_dns_resolver_init(void);
|
||||||
extern void nfs_dns_resolver_destroy(void);
|
extern void nfs_dns_resolver_destroy(void);
|
||||||
|
extern int nfs_dns_resolver_cache_init(struct net *net);
|
||||||
|
extern void nfs_dns_resolver_cache_destroy(struct net *net);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
|
extern ssize_t nfs_dns_resolve_name(struct net *net, char *name,
|
||||||
struct sockaddr *sa, size_t salen);
|
size_t namelen, struct sockaddr *sa, size_t salen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "fscache.h"
|
#include "fscache.h"
|
||||||
#include "dns_resolve.h"
|
#include "dns_resolve.h"
|
||||||
#include "pnfs.h"
|
#include "pnfs.h"
|
||||||
|
#include "netns.h"
|
||||||
|
|
||||||
#define NFSDBG_FACILITY NFSDBG_VFS
|
#define NFSDBG_FACILITY NFSDBG_VFS
|
||||||
|
|
||||||
@ -1552,6 +1553,25 @@ static void nfsiod_stop(void)
|
|||||||
destroy_workqueue(wq);
|
destroy_workqueue(wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nfs_net_id;
|
||||||
|
|
||||||
|
static int nfs_net_init(struct net *net)
|
||||||
|
{
|
||||||
|
return nfs_dns_resolver_cache_init(net);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfs_net_exit(struct net *net)
|
||||||
|
{
|
||||||
|
nfs_dns_resolver_cache_destroy(net);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pernet_operations nfs_net_ops = {
|
||||||
|
.init = nfs_net_init,
|
||||||
|
.exit = nfs_net_exit,
|
||||||
|
.id = &nfs_net_id,
|
||||||
|
.size = sizeof(struct nfs_net),
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize NFS
|
* Initialize NFS
|
||||||
*/
|
*/
|
||||||
@ -1561,9 +1581,13 @@ static int __init init_nfs_fs(void)
|
|||||||
|
|
||||||
err = nfs_idmap_init();
|
err = nfs_idmap_init();
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out9;
|
goto out10;
|
||||||
|
|
||||||
err = nfs_dns_resolver_init();
|
err = nfs_dns_resolver_init();
|
||||||
|
if (err < 0)
|
||||||
|
goto out9;
|
||||||
|
|
||||||
|
err = register_pernet_subsys(&nfs_net_ops);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out8;
|
goto out8;
|
||||||
|
|
||||||
@ -1625,10 +1649,12 @@ out5:
|
|||||||
out6:
|
out6:
|
||||||
nfs_fscache_unregister();
|
nfs_fscache_unregister();
|
||||||
out7:
|
out7:
|
||||||
nfs_dns_resolver_destroy();
|
unregister_pernet_subsys(&nfs_net_ops);
|
||||||
out8:
|
out8:
|
||||||
nfs_idmap_quit();
|
nfs_dns_resolver_destroy();
|
||||||
out9:
|
out9:
|
||||||
|
nfs_idmap_quit();
|
||||||
|
out10:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1640,6 +1666,7 @@ static void __exit exit_nfs_fs(void)
|
|||||||
nfs_destroy_inodecache();
|
nfs_destroy_inodecache();
|
||||||
nfs_destroy_nfspagecache();
|
nfs_destroy_nfspagecache();
|
||||||
nfs_fscache_unregister();
|
nfs_fscache_unregister();
|
||||||
|
unregister_pernet_subsys(&nfs_net_ops);
|
||||||
nfs_dns_resolver_destroy();
|
nfs_dns_resolver_destroy();
|
||||||
nfs_idmap_quit();
|
nfs_idmap_quit();
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
|
13
fs/nfs/netns.h
Normal file
13
fs/nfs/netns.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __NFS_NETNS_H__
|
||||||
|
#define __NFS_NETNS_H__
|
||||||
|
|
||||||
|
#include <net/net_namespace.h>
|
||||||
|
#include <net/netns/generic.h>
|
||||||
|
|
||||||
|
struct nfs_net {
|
||||||
|
struct cache_detail *nfs_dns_resolve;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int nfs_net_id;
|
||||||
|
|
||||||
|
#endif
|
@ -94,13 +94,14 @@ static int nfs4_validate_fspath(struct dentry *dentry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t nfs_parse_server_name(char *string, size_t len,
|
static size_t nfs_parse_server_name(char *string, size_t len,
|
||||||
struct sockaddr *sa, size_t salen)
|
struct sockaddr *sa, size_t salen, struct nfs_server *server)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = rpc_pton(string, len, sa, salen);
|
ret = rpc_pton(string, len, sa, salen);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = nfs_dns_resolve_name(string, len, sa, salen);
|
ret = nfs_dns_resolve_name(server->client->cl_xprt->xprt_net,
|
||||||
|
string, len, sa, salen);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
@ -137,7 +138,8 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
|
mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
|
||||||
mountdata->addr, addr_bufsize);
|
mountdata->addr, addr_bufsize,
|
||||||
|
NFS_SB(mountdata->sb));
|
||||||
if (mountdata->addrlen == 0)
|
if (mountdata->addrlen == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user