Skip to content

Commit

Permalink
NFS: DNS resolver cache per network namespace context introduced
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stanislav Kinsbursky authored and Trond Myklebust committed Jan 31, 2012
1 parent 5c1cacb commit 1b340d0
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 41 deletions.
96 changes: 63 additions & 33 deletions fs/nfs/dns_resolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <linux/sunrpc/clnt.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)
{
ssize_t ret;
Expand Down Expand Up @@ -43,12 +43,11 @@ ssize_t nfs_dns_resolve_name(char *name, size_t namelen,

#include "dns_resolve.h"
#include "cache_lib.h"
#include "netns.h"

#define NFS_DNS_HASHBITS 4
#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 cache_head h;

Expand Down Expand Up @@ -259,21 +258,6 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
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,
struct nfs_dns_ent *key,
struct nfs_dns_ent **item,
Expand Down Expand Up @@ -336,46 +320,92 @@ static int do_cache_lookup_wait(struct cache_detail *cd,
return ret;
}

ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
struct sockaddr *sa, size_t salen)
ssize_t nfs_dns_resolve_name(struct net *net, char *name,
size_t namelen, struct sockaddr *sa, size_t salen)
{
struct nfs_dns_ent key = {
.hostname = name,
.namelen = namelen,
};
struct nfs_dns_ent *item = NULL;
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 (salen >= item->addrlen) {
memcpy(sa, &item->addr, item->addrlen);
ret = item->addrlen;
} else
ret = -EOVERFLOW;
cache_put(&item->h, &nfs_dns_resolve);
cache_put(&item->h, nn->nfs_dns_resolve);
} else if (ret == -ENOENT)
ret = -ESRCH;
return ret;
}

int nfs_dns_resolver_init(void)
int nfs_dns_resolver_cache_init(struct net *net)
{
int err;
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;

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;
}
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)
{
return 0;
}

void nfs_dns_resolver_destroy(void)
{
nfs_cache_unregister_net(&init_net, &nfs_dns_resolve);
nfs_cache_destroy(&nfs_dns_resolve);
}

#endif
14 changes: 12 additions & 2 deletions fs/nfs/dns_resolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,22 @@ static inline int nfs_dns_resolver_init(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
extern int nfs_dns_resolver_init(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

extern ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
struct sockaddr *sa, size_t salen);
extern ssize_t nfs_dns_resolve_name(struct net *net, char *name,
size_t namelen, struct sockaddr *sa, size_t salen);

#endif
33 changes: 30 additions & 3 deletions fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "fscache.h"
#include "dns_resolve.h"
#include "pnfs.h"
#include "netns.h"

#define NFSDBG_FACILITY NFSDBG_VFS

Expand Down Expand Up @@ -1552,6 +1553,25 @@ static void nfsiod_stop(void)
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
*/
Expand All @@ -1561,9 +1581,13 @@ static int __init init_nfs_fs(void)

err = nfs_idmap_init();
if (err < 0)
goto out9;
goto out10;

err = nfs_dns_resolver_init();
if (err < 0)
goto out9;

err = register_pernet_subsys(&nfs_net_ops);
if (err < 0)
goto out8;

Expand Down Expand Up @@ -1625,10 +1649,12 @@ static int __init init_nfs_fs(void)
out6:
nfs_fscache_unregister();
out7:
nfs_dns_resolver_destroy();
unregister_pernet_subsys(&nfs_net_ops);
out8:
nfs_idmap_quit();
nfs_dns_resolver_destroy();
out9:
nfs_idmap_quit();
out10:
return err;
}

Expand All @@ -1640,6 +1666,7 @@ static void __exit exit_nfs_fs(void)
nfs_destroy_inodecache();
nfs_destroy_nfspagecache();
nfs_fscache_unregister();
unregister_pernet_subsys(&nfs_net_ops);
nfs_dns_resolver_destroy();
nfs_idmap_quit();
#ifdef CONFIG_PROC_FS
Expand Down
13 changes: 13 additions & 0 deletions fs/nfs/netns.h
Original file line number Diff line number Diff line change
@@ -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
8 changes: 5 additions & 3 deletions fs/nfs/nfs4namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,14 @@ static int nfs4_validate_fspath(struct dentry *dentry,
}

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;

ret = rpc_pton(string, len, sa, salen);
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)
ret = 0;
}
Expand Down Expand Up @@ -137,7 +138,8 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
continue;

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)
continue;

Expand Down

0 comments on commit 1b340d0

Please sign in to comment.