aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4idmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4idmap.c')
-rw-r--r--fs/nfsd/nfs4idmap.c113
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 @@
36#include <linux/seq_file.h> 36#include <linux/seq_file.h>
37#include <linux/sched.h> 37#include <linux/sched.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/sunrpc/svc_xprt.h>
39#include <net/net_namespace.h> 40#include <net/net_namespace.h>
40#include "idmap.h" 41#include "idmap.h"
41#include "nfsd.h" 42#include "nfsd.h"
43#include "netns.h"
42 44
43/* 45/*
44 * Turn off idmapping when using AUTH_SYS. 46 * Turn off idmapping when using AUTH_SYS.
@@ -107,8 +109,6 @@ ent_alloc(void)
107 * ID -> Name cache 109 * ID -> Name cache
108 */ 110 */
109 111
110static struct cache_head *idtoname_table[ENT_HASHMAX];
111
112static uint32_t 112static uint32_t
113idtoname_hash(struct ent *ent) 113idtoname_hash(struct ent *ent)
114{ 114{
@@ -183,13 +183,13 @@ warn_no_idmapd(struct cache_detail *detail, int has_died)
183 183
184 184
185static int idtoname_parse(struct cache_detail *, char *, int); 185static int idtoname_parse(struct cache_detail *, char *, int);
186static struct ent *idtoname_lookup(struct ent *); 186static struct ent *idtoname_lookup(struct cache_detail *, struct ent *);
187static struct ent *idtoname_update(struct ent *, struct ent *); 187static struct ent *idtoname_update(struct cache_detail *, struct ent *,
188 struct ent *);
188 189
189static struct cache_detail idtoname_cache = { 190static struct cache_detail idtoname_cache_template = {
190 .owner = THIS_MODULE, 191 .owner = THIS_MODULE,
191 .hash_size = ENT_HASHMAX, 192 .hash_size = ENT_HASHMAX,
192 .hash_table = idtoname_table,
193 .name = "nfs4.idtoname", 193 .name = "nfs4.idtoname",
194 .cache_put = ent_put, 194 .cache_put = ent_put,
195 .cache_upcall = idtoname_upcall, 195 .cache_upcall = idtoname_upcall,
@@ -244,7 +244,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
244 goto out; 244 goto out;
245 245
246 error = -ENOMEM; 246 error = -ENOMEM;
247 res = idtoname_lookup(&ent); 247 res = idtoname_lookup(cd, &ent);
248 if (!res) 248 if (!res)
249 goto out; 249 goto out;
250 250
@@ -260,11 +260,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
260 else 260 else
261 memcpy(ent.name, buf1, sizeof(ent.name)); 261 memcpy(ent.name, buf1, sizeof(ent.name));
262 error = -ENOMEM; 262 error = -ENOMEM;
263 res = idtoname_update(&ent, res); 263 res = idtoname_update(cd, &ent, res);
264 if (res == NULL) 264 if (res == NULL)
265 goto out; 265 goto out;
266 266
267 cache_put(&res->h, &idtoname_cache); 267 cache_put(&res->h, cd);
268 268
269 error = 0; 269 error = 0;
270out: 270out:
@@ -275,10 +275,9 @@ out:
275 275
276 276
277static struct ent * 277static struct ent *
278idtoname_lookup(struct ent *item) 278idtoname_lookup(struct cache_detail *cd, struct ent *item)
279{ 279{
280 struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, 280 struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,
281 &item->h,
282 idtoname_hash(item)); 281 idtoname_hash(item));
283 if (ch) 282 if (ch)
284 return container_of(ch, struct ent, h); 283 return container_of(ch, struct ent, h);
@@ -287,10 +286,9 @@ idtoname_lookup(struct ent *item)
287} 286}
288 287
289static struct ent * 288static struct ent *
290idtoname_update(struct ent *new, struct ent *old) 289idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old)
291{ 290{
292 struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, 291 struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,
293 &new->h, &old->h,
294 idtoname_hash(new)); 292 idtoname_hash(new));
295 if (ch) 293 if (ch)
296 return container_of(ch, struct ent, h); 294 return container_of(ch, struct ent, h);
@@ -303,8 +301,6 @@ idtoname_update(struct ent *new, struct ent *old)
303 * Name -> ID cache 301 * Name -> ID cache
304 */ 302 */
305 303
306static struct cache_head *nametoid_table[ENT_HASHMAX];
307
308static inline int 304static inline int
309nametoid_hash(struct ent *ent) 305nametoid_hash(struct ent *ent)
310{ 306{
@@ -359,14 +355,14 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
359 return 0; 355 return 0;
360} 356}
361 357
362static struct ent *nametoid_lookup(struct ent *); 358static struct ent *nametoid_lookup(struct cache_detail *, struct ent *);
363static struct ent *nametoid_update(struct ent *, struct ent *); 359static struct ent *nametoid_update(struct cache_detail *, struct ent *,
360 struct ent *);
364static int nametoid_parse(struct cache_detail *, char *, int); 361static int nametoid_parse(struct cache_detail *, char *, int);
365 362
366static struct cache_detail nametoid_cache = { 363static struct cache_detail nametoid_cache_template = {
367 .owner = THIS_MODULE, 364 .owner = THIS_MODULE,
368 .hash_size = ENT_HASHMAX, 365 .hash_size = ENT_HASHMAX,
369 .hash_table = nametoid_table,
370 .name = "nfs4.nametoid", 366 .name = "nfs4.nametoid",
371 .cache_put = ent_put, 367 .cache_put = ent_put,
372 .cache_upcall = nametoid_upcall, 368 .cache_upcall = nametoid_upcall,
@@ -426,14 +422,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
426 set_bit(CACHE_NEGATIVE, &ent.h.flags); 422 set_bit(CACHE_NEGATIVE, &ent.h.flags);
427 423
428 error = -ENOMEM; 424 error = -ENOMEM;
429 res = nametoid_lookup(&ent); 425 res = nametoid_lookup(cd, &ent);
430 if (res == NULL) 426 if (res == NULL)
431 goto out; 427 goto out;
432 res = nametoid_update(&ent, res); 428 res = nametoid_update(cd, &ent, res);
433 if (res == NULL) 429 if (res == NULL)
434 goto out; 430 goto out;
435 431
436 cache_put(&res->h, &nametoid_cache); 432 cache_put(&res->h, cd);
437 error = 0; 433 error = 0;
438out: 434out:
439 kfree(buf1); 435 kfree(buf1);
@@ -443,10 +439,9 @@ out:
443 439
444 440
445static struct ent * 441static struct ent *
446nametoid_lookup(struct ent *item) 442nametoid_lookup(struct cache_detail *cd, struct ent *item)
447{ 443{
448 struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, 444 struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,
449 &item->h,
450 nametoid_hash(item)); 445 nametoid_hash(item));
451 if (ch) 446 if (ch)
452 return container_of(ch, struct ent, h); 447 return container_of(ch, struct ent, h);
@@ -455,10 +450,9 @@ nametoid_lookup(struct ent *item)
455} 450}
456 451
457static struct ent * 452static struct ent *
458nametoid_update(struct ent *new, struct ent *old) 453nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old)
459{ 454{
460 struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, 455 struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,
461 &new->h, &old->h,
462 nametoid_hash(new)); 456 nametoid_hash(new));
463 if (ch) 457 if (ch)
464 return container_of(ch, struct ent, h); 458 return container_of(ch, struct ent, h);
@@ -471,34 +465,55 @@ nametoid_update(struct ent *new, struct ent *old)
471 */ 465 */
472 466
473int 467int
474nfsd_idmap_init(void) 468nfsd_idmap_init(struct net *net)
475{ 469{
476 int rv; 470 int rv;
471 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
477 472
478 rv = cache_register_net(&idtoname_cache, &init_net); 473 nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net);
474 if (IS_ERR(nn->idtoname_cache))
475 return PTR_ERR(nn->idtoname_cache);
476 rv = cache_register_net(nn->idtoname_cache, net);
479 if (rv) 477 if (rv)
480 return rv; 478 goto destroy_idtoname_cache;
481 rv = cache_register_net(&nametoid_cache, &init_net); 479 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
480 if (IS_ERR(nn->nametoid_cache)) {
481 rv = PTR_ERR(nn->idtoname_cache);
482 goto unregister_idtoname_cache;
483 }
484 rv = cache_register_net(nn->nametoid_cache, net);
482 if (rv) 485 if (rv)
483 cache_unregister_net(&idtoname_cache, &init_net); 486 goto destroy_nametoid_cache;
487 return 0;
488
489destroy_nametoid_cache:
490 cache_destroy_net(nn->nametoid_cache, net);
491unregister_idtoname_cache:
492 cache_unregister_net(nn->idtoname_cache, net);
493destroy_idtoname_cache:
494 cache_destroy_net(nn->idtoname_cache, net);
484 return rv; 495 return rv;
485} 496}
486 497
487void 498void
488nfsd_idmap_shutdown(void) 499nfsd_idmap_shutdown(struct net *net)
489{ 500{
490 cache_unregister_net(&idtoname_cache, &init_net); 501 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
491 cache_unregister_net(&nametoid_cache, &init_net); 502
503 cache_unregister_net(nn->idtoname_cache, net);
504 cache_unregister_net(nn->nametoid_cache, net);
505 cache_destroy_net(nn->idtoname_cache, net);
506 cache_destroy_net(nn->nametoid_cache, net);
492} 507}
493 508
494static int 509static int
495idmap_lookup(struct svc_rqst *rqstp, 510idmap_lookup(struct svc_rqst *rqstp,
496 struct ent *(*lookup_fn)(struct ent *), struct ent *key, 511 struct ent *(*lookup_fn)(struct cache_detail *, struct ent *),
497 struct cache_detail *detail, struct ent **item) 512 struct ent *key, struct cache_detail *detail, struct ent **item)
498{ 513{
499 int ret; 514 int ret;
500 515
501 *item = lookup_fn(key); 516 *item = lookup_fn(detail, key);
502 if (!*item) 517 if (!*item)
503 return -ENOMEM; 518 return -ENOMEM;
504 retry: 519 retry:
@@ -506,7 +521,7 @@ idmap_lookup(struct svc_rqst *rqstp,
506 521
507 if (ret == -ETIMEDOUT) { 522 if (ret == -ETIMEDOUT) {
508 struct ent *prev_item = *item; 523 struct ent *prev_item = *item;
509 *item = lookup_fn(key); 524 *item = lookup_fn(detail, key);
510 if (*item != prev_item) 525 if (*item != prev_item)
511 goto retry; 526 goto retry;
512 cache_put(&(*item)->h, detail); 527 cache_put(&(*item)->h, detail);
@@ -531,19 +546,20 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
531 .type = type, 546 .type = type,
532 }; 547 };
533 int ret; 548 int ret;
549 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
534 550
535 if (namelen + 1 > sizeof(key.name)) 551 if (namelen + 1 > sizeof(key.name))
536 return nfserr_badowner; 552 return nfserr_badowner;
537 memcpy(key.name, name, namelen); 553 memcpy(key.name, name, namelen);
538 key.name[namelen] = '\0'; 554 key.name[namelen] = '\0';
539 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 555 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
540 ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); 556 ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item);
541 if (ret == -ENOENT) 557 if (ret == -ENOENT)
542 return nfserr_badowner; 558 return nfserr_badowner;
543 if (ret) 559 if (ret)
544 return nfserrno(ret); 560 return nfserrno(ret);
545 *id = item->id; 561 *id = item->id;
546 cache_put(&item->h, &nametoid_cache); 562 cache_put(&item->h, nn->nametoid_cache);
547 return 0; 563 return 0;
548} 564}
549 565
@@ -555,9 +571,10 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
555 .type = type, 571 .type = type,
556 }; 572 };
557 int ret; 573 int ret;
574 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
558 575
559 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 576 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
560 ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item); 577 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
561 if (ret == -ENOENT) 578 if (ret == -ENOENT)
562 return sprintf(name, "%u", id); 579 return sprintf(name, "%u", id);
563 if (ret) 580 if (ret)
@@ -565,7 +582,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
565 ret = strlen(item->name); 582 ret = strlen(item->name);
566 BUG_ON(ret > IDMAP_NAMESZ); 583 BUG_ON(ret > IDMAP_NAMESZ);
567 memcpy(name, item->name, ret); 584 memcpy(name, item->name, ret);
568 cache_put(&item->h, &idtoname_cache); 585 cache_put(&item->h, nn->idtoname_cache);
569 return ret; 586 return ret;
570} 587}
571 588
@@ -588,7 +605,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel
588static __be32 605static __be32
589do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id) 606do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
590{ 607{
591 if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS) 608 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
592 if (numeric_name_to_id(rqstp, type, name, namelen, id)) 609 if (numeric_name_to_id(rqstp, type, name, namelen, id))
593 return 0; 610 return 0;
594 /* 611 /*
@@ -601,7 +618,7 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u
601static int 618static int
602do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) 619do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
603{ 620{
604 if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS) 621 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
605 return sprintf(name, "%u", id); 622 return sprintf(name, "%u", id);
606 return idmap_id_to_name(rqstp, type, id, name); 623 return idmap_id_to_name(rqstp, type, id, name);
607} 624}