Commit 90d51b02 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by J. Bruce Fields

sunrpc: Make the ip_map_cache be per-net

Everything that is required for that already exists:
* the per-net cache registration with respective proc entries
* the context (struct net) is available in all the users
Signed-off-by: default avatarPavel Emelyanov <xemul@openvz.org>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 4f42d0d5
...@@ -4,10 +4,16 @@ ...@@ -4,10 +4,16 @@
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/netns/generic.h> #include <net/netns/generic.h>
struct cache_detail;
struct sunrpc_net { struct sunrpc_net {
struct proc_dir_entry *proc_net_rpc; struct proc_dir_entry *proc_net_rpc;
struct cache_detail *ip_map_cache;
}; };
extern int sunrpc_net_id; extern int sunrpc_net_id;
int ip_map_cache_create(struct net *);
void ip_map_cache_destroy(struct net *);
#endif #endif
...@@ -34,14 +34,21 @@ static __net_init int sunrpc_init_net(struct net *net) ...@@ -34,14 +34,21 @@ static __net_init int sunrpc_init_net(struct net *net)
if (err) if (err)
goto err_proc; goto err_proc;
err = ip_map_cache_create(net);
if (err)
goto err_ipmap;
return 0; return 0;
err_ipmap:
rpc_proc_exit(net);
err_proc: err_proc:
return err; return err;
} }
static __net_exit void sunrpc_exit_net(struct net *net) static __net_exit void sunrpc_exit_net(struct net *net)
{ {
ip_map_cache_destroy(net);
rpc_proc_exit(net); rpc_proc_exit(net);
} }
...@@ -52,7 +59,7 @@ static struct pernet_operations sunrpc_net_ops = { ...@@ -52,7 +59,7 @@ static struct pernet_operations sunrpc_net_ops = {
.size = sizeof(struct sunrpc_net), .size = sizeof(struct sunrpc_net),
}; };
extern struct cache_detail ip_map_cache, unix_gid_cache; extern struct cache_detail unix_gid_cache;
extern void cleanup_rpcb_clnt(void); extern void cleanup_rpcb_clnt(void);
...@@ -77,7 +84,6 @@ init_sunrpc(void) ...@@ -77,7 +84,6 @@ init_sunrpc(void)
#ifdef RPC_DEBUG #ifdef RPC_DEBUG
rpc_register_sysctl(); rpc_register_sysctl();
#endif #endif
cache_register(&ip_map_cache);
cache_register(&unix_gid_cache); cache_register(&unix_gid_cache);
svc_init_xprt_sock(); /* svc sock transport */ svc_init_xprt_sock(); /* svc sock transport */
init_socket_xprt(); /* clnt sock transport */ init_socket_xprt(); /* clnt sock transport */
...@@ -102,7 +108,6 @@ cleanup_sunrpc(void) ...@@ -102,7 +108,6 @@ cleanup_sunrpc(void)
svc_cleanup_xprt_sock(); svc_cleanup_xprt_sock();
unregister_rpc_pipefs(); unregister_rpc_pipefs();
rpc_destroy_mempool(); rpc_destroy_mempool();
cache_unregister(&ip_map_cache);
cache_unregister(&unix_gid_cache); cache_unregister(&unix_gid_cache);
unregister_pernet_subsys(&sunrpc_net_ops); unregister_pernet_subsys(&sunrpc_net_ops);
#ifdef RPC_DEBUG #ifdef RPC_DEBUG
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include "netns.h"
/* /*
* AUTHUNIX and AUTHNULL credentials are both handled here. * AUTHUNIX and AUTHNULL credentials are both handled here.
* AUTHNULL is treated just like AUTHUNIX except that the uid/gid * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
...@@ -92,7 +94,6 @@ struct ip_map { ...@@ -92,7 +94,6 @@ struct ip_map {
struct unix_domain *m_client; struct unix_domain *m_client;
int m_add_change; int m_add_change;
}; };
static struct cache_head *ip_table[IP_HASHMAX];
static void ip_map_put(struct kref *kref) static void ip_map_put(struct kref *kref)
{ {
...@@ -294,21 +295,6 @@ static int ip_map_show(struct seq_file *m, ...@@ -294,21 +295,6 @@ static int ip_map_show(struct seq_file *m,
} }
struct cache_detail ip_map_cache = {
.owner = THIS_MODULE,
.hash_size = IP_HASHMAX,
.hash_table = ip_table,
.name = "auth.unix.ip",
.cache_put = ip_map_put,
.cache_upcall = ip_map_upcall,
.cache_parse = ip_map_parse,
.cache_show = ip_map_show,
.match = ip_map_match,
.init = ip_map_init,
.update = update,
.alloc = ip_map_alloc,
};
static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
struct in6_addr *addr) struct in6_addr *addr)
{ {
...@@ -330,7 +316,10 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, ...@@ -330,7 +316,10 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
static inline struct ip_map *ip_map_lookup(struct net *net, char *class, static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
struct in6_addr *addr) struct in6_addr *addr)
{ {
return __ip_map_lookup(&ip_map_cache, class, addr); struct sunrpc_net *sn;
sn = net_generic(net, sunrpc_net_id);
return __ip_map_lookup(sn->ip_map_cache, class, addr);
} }
static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
...@@ -364,7 +353,10 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, ...@@ -364,7 +353,10 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
static inline int ip_map_update(struct net *net, struct ip_map *ipm, static inline int ip_map_update(struct net *net, struct ip_map *ipm,
struct unix_domain *udom, time_t expiry) struct unix_domain *udom, time_t expiry)
{ {
return __ip_map_update(&ip_map_cache, ipm, udom, expiry); struct sunrpc_net *sn;
sn = net_generic(net, sunrpc_net_id);
return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
} }
int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom) int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
...@@ -400,12 +392,14 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr) ...@@ -400,12 +392,14 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
{ {
struct ip_map *ipm; struct ip_map *ipm;
struct auth_domain *rv; struct auth_domain *rv;
struct sunrpc_net *sn;
sn = net_generic(net, sunrpc_net_id);
ipm = ip_map_lookup(net, "nfsd", addr); ipm = ip_map_lookup(net, "nfsd", addr);
if (!ipm) if (!ipm)
return NULL; return NULL;
if (cache_check(&ip_map_cache, &ipm->h, NULL)) if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
return NULL; return NULL;
if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
...@@ -416,14 +410,21 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr) ...@@ -416,14 +410,21 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
rv = &ipm->m_client->h; rv = &ipm->m_client->h;
kref_get(&rv->ref); kref_get(&rv->ref);
} }
cache_put(&ipm->h, &ip_map_cache); cache_put(&ipm->h, sn->ip_map_cache);
return rv; return rv;
} }
EXPORT_SYMBOL_GPL(auth_unix_lookup); EXPORT_SYMBOL_GPL(auth_unix_lookup);
void svcauth_unix_purge(void) void svcauth_unix_purge(void)
{ {
cache_purge(&ip_map_cache); struct net *net;
for_each_net(net) {
struct sunrpc_net *sn;
sn = net_generic(net, sunrpc_net_id);
cache_purge(sn->ip_map_cache);
}
} }
EXPORT_SYMBOL_GPL(svcauth_unix_purge); EXPORT_SYMBOL_GPL(svcauth_unix_purge);
...@@ -431,6 +432,7 @@ static inline struct ip_map * ...@@ -431,6 +432,7 @@ static inline struct ip_map *
ip_map_cached_get(struct svc_xprt *xprt) ip_map_cached_get(struct svc_xprt *xprt)
{ {
struct ip_map *ipm = NULL; struct ip_map *ipm = NULL;
struct sunrpc_net *sn;
if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
spin_lock(&xprt->xpt_lock); spin_lock(&xprt->xpt_lock);
...@@ -442,9 +444,10 @@ ip_map_cached_get(struct svc_xprt *xprt) ...@@ -442,9 +444,10 @@ ip_map_cached_get(struct svc_xprt *xprt)
* remembered, e.g. by a second mount from the * remembered, e.g. by a second mount from the
* same IP address. * same IP address.
*/ */
sn = net_generic(xprt->xpt_net, sunrpc_net_id);
xprt->xpt_auth_cache = NULL; xprt->xpt_auth_cache = NULL;
spin_unlock(&xprt->xpt_lock); spin_unlock(&xprt->xpt_lock);
cache_put(&ipm->h, &ip_map_cache); cache_put(&ipm->h, sn->ip_map_cache);
return NULL; return NULL;
} }
cache_get(&ipm->h); cache_get(&ipm->h);
...@@ -466,8 +469,12 @@ ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm) ...@@ -466,8 +469,12 @@ ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
} }
spin_unlock(&xprt->xpt_lock); spin_unlock(&xprt->xpt_lock);
} }
if (ipm) if (ipm) {
cache_put(&ipm->h, &ip_map_cache); struct sunrpc_net *sn;
sn = net_generic(xprt->xpt_net, sunrpc_net_id);
cache_put(&ipm->h, sn->ip_map_cache);
}
} }
void void
...@@ -476,8 +483,12 @@ svcauth_unix_info_release(struct svc_xprt *xpt) ...@@ -476,8 +483,12 @@ svcauth_unix_info_release(struct svc_xprt *xpt)
struct ip_map *ipm; struct ip_map *ipm;
ipm = xpt->xpt_auth_cache; ipm = xpt->xpt_auth_cache;
if (ipm != NULL) if (ipm != NULL) {
cache_put(&ipm->h, &ip_map_cache); struct sunrpc_net *sn;
sn = net_generic(xpt->xpt_net, sunrpc_net_id);
cache_put(&ipm->h, sn->ip_map_cache);
}
} }
/**************************************************************************** /****************************************************************************
...@@ -707,6 +718,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) ...@@ -707,6 +718,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
struct group_info *gi; struct group_info *gi;
struct svc_cred *cred = &rqstp->rq_cred; struct svc_cred *cred = &rqstp->rq_cred;
struct svc_xprt *xprt = rqstp->rq_xprt; struct svc_xprt *xprt = rqstp->rq_xprt;
struct net *net = xprt->xpt_net;
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
switch (rqstp->rq_addr.ss_family) { switch (rqstp->rq_addr.ss_family) {
case AF_INET: case AF_INET:
...@@ -727,13 +740,13 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) ...@@ -727,13 +740,13 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
ipm = ip_map_cached_get(xprt); ipm = ip_map_cached_get(xprt);
if (ipm == NULL) if (ipm == NULL)
ipm = ip_map_lookup(&init_net, rqstp->rq_server->sv_program->pg_class, ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
&sin6->sin6_addr); &sin6->sin6_addr);
if (ipm == NULL) if (ipm == NULL)
return SVC_DENIED; return SVC_DENIED;
switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
default: default:
BUG(); BUG();
case -ETIMEDOUT: case -ETIMEDOUT:
...@@ -905,3 +918,56 @@ struct auth_ops svcauth_unix = { ...@@ -905,3 +918,56 @@ struct auth_ops svcauth_unix = {
.set_client = svcauth_unix_set_client, .set_client = svcauth_unix_set_client,
}; };
int ip_map_cache_create(struct net *net)
{
int err = -ENOMEM;
struct cache_detail *cd;
struct cache_head **tbl;
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
if (cd == NULL)
goto err_cd;
tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL);
if (tbl == NULL)
goto err_tbl;
cd->owner = THIS_MODULE,
cd->hash_size = IP_HASHMAX,
cd->hash_table = tbl,
cd->name = "auth.unix.ip",
cd->cache_put = ip_map_put,
cd->cache_upcall = ip_map_upcall,
cd->cache_parse = ip_map_parse,
cd->cache_show = ip_map_show,
cd->match = ip_map_match,
cd->init = ip_map_init,
cd->update = update,
cd->alloc = ip_map_alloc,
err = cache_register_net(cd, net);
if (err)
goto err_reg;
sn->ip_map_cache = cd;
return 0;
err_reg:
kfree(tbl);
err_tbl:
kfree(cd);
err_cd:
return err;
}
void ip_map_cache_destroy(struct net *net)
{
struct sunrpc_net *sn;
sn = net_generic(net, sunrpc_net_id);
cache_purge(sn->ip_map_cache);
cache_unregister_net(sn->ip_map_cache, net);
kfree(sn->ip_map_cache->hash_table);
kfree(sn->ip_map_cache);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment