diff options
Diffstat (limited to 'fs/nfsd/nfs4idmap.c')
| -rw-r--r-- | fs/nfsd/nfs4idmap.c | 113 | 
1 files changed, 65 insertions, 48 deletions
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 322d11ce06a..dae36f1dee9 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -36,9 +36,11 @@  #include <linux/seq_file.h>  #include <linux/sched.h>  #include <linux/slab.h> +#include <linux/sunrpc/svc_xprt.h>  #include <net/net_namespace.h>  #include "idmap.h"  #include "nfsd.h" +#include "netns.h"  /*   * Turn off idmapping when using AUTH_SYS. @@ -107,8 +109,6 @@ ent_alloc(void)   * ID -> Name cache   */ -static struct cache_head *idtoname_table[ENT_HASHMAX]; -  static uint32_t  idtoname_hash(struct ent *ent)  { @@ -183,13 +183,13 @@ warn_no_idmapd(struct cache_detail *detail, int has_died)  static int         idtoname_parse(struct cache_detail *, char *, int); -static struct ent *idtoname_lookup(struct ent *); -static struct ent *idtoname_update(struct ent *, struct ent *); +static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); +static struct ent *idtoname_update(struct cache_detail *, struct ent *, +				   struct ent *); -static struct cache_detail idtoname_cache = { +static struct cache_detail idtoname_cache_template = {  	.owner		= THIS_MODULE,  	.hash_size	= ENT_HASHMAX, -	.hash_table	= idtoname_table,  	.name		= "nfs4.idtoname",  	.cache_put	= ent_put,  	.cache_upcall	= idtoname_upcall, @@ -244,7 +244,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)  		goto out;  	error = -ENOMEM; -	res = idtoname_lookup(&ent); +	res = idtoname_lookup(cd, &ent);  	if (!res)  		goto out; @@ -260,11 +260,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)  	else  		memcpy(ent.name, buf1, sizeof(ent.name));  	error = -ENOMEM; -	res = idtoname_update(&ent, res); +	res = idtoname_update(cd, &ent, res);  	if (res == NULL)  		goto out; -	cache_put(&res->h, &idtoname_cache); +	cache_put(&res->h, cd);  	error = 0;  out: @@ -275,10 +275,9 @@ out:  static struct ent * -idtoname_lookup(struct ent *item) +idtoname_lookup(struct cache_detail *cd, struct ent *item)  { -	struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, -						    &item->h, +	struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,  						    idtoname_hash(item));  	if (ch)  		return container_of(ch, struct ent, h); @@ -287,10 +286,9 @@ idtoname_lookup(struct ent *item)  }  static struct ent * -idtoname_update(struct ent *new, struct ent *old) +idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old)  { -	struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, -						    &new->h, &old->h, +	struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,  						    idtoname_hash(new));  	if (ch)  		return container_of(ch, struct ent, h); @@ -303,8 +301,6 @@ idtoname_update(struct ent *new, struct ent *old)   * Name -> ID cache   */ -static struct cache_head *nametoid_table[ENT_HASHMAX]; -  static inline int  nametoid_hash(struct ent *ent)  { @@ -359,14 +355,14 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)  	return 0;  } -static struct ent *nametoid_lookup(struct ent *); -static struct ent *nametoid_update(struct ent *, struct ent *); +static struct ent *nametoid_lookup(struct cache_detail *, struct ent *); +static struct ent *nametoid_update(struct cache_detail *, struct ent *, +				   struct ent *);  static int         nametoid_parse(struct cache_detail *, char *, int); -static struct cache_detail nametoid_cache = { +static struct cache_detail nametoid_cache_template = {  	.owner		= THIS_MODULE,  	.hash_size	= ENT_HASHMAX, -	.hash_table	= nametoid_table,  	.name		= "nfs4.nametoid",  	.cache_put	= ent_put,  	.cache_upcall	= nametoid_upcall, @@ -426,14 +422,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen)  		set_bit(CACHE_NEGATIVE, &ent.h.flags);  	error = -ENOMEM; -	res = nametoid_lookup(&ent); +	res = nametoid_lookup(cd, &ent);  	if (res == NULL)  		goto out; -	res = nametoid_update(&ent, res); +	res = nametoid_update(cd, &ent, res);  	if (res == NULL)  		goto out; -	cache_put(&res->h, &nametoid_cache); +	cache_put(&res->h, cd);  	error = 0;  out:  	kfree(buf1); @@ -443,10 +439,9 @@ out:  static struct ent * -nametoid_lookup(struct ent *item) +nametoid_lookup(struct cache_detail *cd, struct ent *item)  { -	struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, -						    &item->h, +	struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,  						    nametoid_hash(item));  	if (ch)  		return container_of(ch, struct ent, h); @@ -455,10 +450,9 @@ nametoid_lookup(struct ent *item)  }  static struct ent * -nametoid_update(struct ent *new, struct ent *old) +nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old)  { -	struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, -						    &new->h, &old->h, +	struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,  						    nametoid_hash(new));  	if (ch)  		return container_of(ch, struct ent, h); @@ -471,34 +465,55 @@ nametoid_update(struct ent *new, struct ent *old)   */  int -nfsd_idmap_init(void) +nfsd_idmap_init(struct net *net)  {  	int rv; +	struct nfsd_net *nn = net_generic(net, nfsd_net_id); -	rv = cache_register_net(&idtoname_cache, &init_net); +	nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net); +	if (IS_ERR(nn->idtoname_cache)) +		return PTR_ERR(nn->idtoname_cache); +	rv = cache_register_net(nn->idtoname_cache, net);  	if (rv) -		return rv; -	rv = cache_register_net(&nametoid_cache, &init_net); +		goto destroy_idtoname_cache; +	nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); +	if (IS_ERR(nn->nametoid_cache)) { +		rv = PTR_ERR(nn->idtoname_cache); +		goto unregister_idtoname_cache; +	} +	rv = cache_register_net(nn->nametoid_cache, net);  	if (rv) -		cache_unregister_net(&idtoname_cache, &init_net); +		goto destroy_nametoid_cache; +	return 0; + +destroy_nametoid_cache: +	cache_destroy_net(nn->nametoid_cache, net); +unregister_idtoname_cache: +	cache_unregister_net(nn->idtoname_cache, net); +destroy_idtoname_cache: +	cache_destroy_net(nn->idtoname_cache, net);  	return rv;  }  void -nfsd_idmap_shutdown(void) +nfsd_idmap_shutdown(struct net *net)  { -	cache_unregister_net(&idtoname_cache, &init_net); -	cache_unregister_net(&nametoid_cache, &init_net); +	struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +	cache_unregister_net(nn->idtoname_cache, net); +	cache_unregister_net(nn->nametoid_cache, net); +	cache_destroy_net(nn->idtoname_cache, net); +	cache_destroy_net(nn->nametoid_cache, net);  }  static int  idmap_lookup(struct svc_rqst *rqstp, -		struct ent *(*lookup_fn)(struct ent *), struct ent *key, -		struct cache_detail *detail, struct ent **item) +		struct ent *(*lookup_fn)(struct cache_detail *, struct ent *), +		struct ent *key, struct cache_detail *detail, struct ent **item)  {  	int ret; -	*item = lookup_fn(key); +	*item = lookup_fn(detail, key);  	if (!*item)  		return -ENOMEM;   retry: @@ -506,7 +521,7 @@ idmap_lookup(struct svc_rqst *rqstp,  	if (ret == -ETIMEDOUT) {  		struct ent *prev_item = *item; -		*item = lookup_fn(key); +		*item = lookup_fn(detail, key);  		if (*item != prev_item)  			goto retry;  		cache_put(&(*item)->h, detail); @@ -531,19 +546,20 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen  		.type = type,  	};  	int ret; +	struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);  	if (namelen + 1 > sizeof(key.name))  		return nfserr_badowner;  	memcpy(key.name, name, namelen);  	key.name[namelen] = '\0';  	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); -	ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); +	ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item);  	if (ret == -ENOENT)  		return nfserr_badowner;  	if (ret)  		return nfserrno(ret);  	*id = item->id; -	cache_put(&item->h, &nametoid_cache); +	cache_put(&item->h, nn->nametoid_cache);  	return 0;  } @@ -555,9 +571,10 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)  		.type = type,  	};  	int ret; +	struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);  	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); -	ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item); +	ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);  	if (ret == -ENOENT)  		return sprintf(name, "%u", id);  	if (ret) @@ -565,7 +582,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)  	ret = strlen(item->name);  	BUG_ON(ret > IDMAP_NAMESZ);  	memcpy(name, item->name, ret); -	cache_put(&item->h, &idtoname_cache); +	cache_put(&item->h, nn->idtoname_cache);  	return ret;  } @@ -588,7 +605,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel  static __be32  do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)  { -	if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS) +	if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)  		if (numeric_name_to_id(rqstp, type, name, namelen, id))  			return 0;  		/* @@ -601,7 +618,7 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u  static int  do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)  { -	if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS) +	if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)  		return sprintf(name, "%u", id);  	return idmap_id_to_name(rqstp, type, id, name);  }  |