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: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
4f42d0d53c
commit
90d51b02fd
@ -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)
|
|||||||
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 = {
|
|||||||
.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)
|
|||||||
#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)
|
|||||||
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 @@
|
|||||||
|
|
||||||
#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 {
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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 *
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 = {
|
|||||||
.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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user