Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -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
+8 −3
Original line number Original line Diff line number Diff line
@@ -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
+94 −28
Original line number Original line Diff line number Diff line
@@ -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);
}