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 @@ | |||
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 | ||
110 | static struct cache_head *idtoname_table[ENT_HASHMAX]; | ||
111 | |||
112 | static uint32_t | 112 | static uint32_t |
113 | idtoname_hash(struct ent *ent) | 113 | idtoname_hash(struct ent *ent) |
114 | { | 114 | { |
@@ -183,13 +183,13 @@ warn_no_idmapd(struct cache_detail *detail, int has_died) | |||
183 | 183 | ||
184 | 184 | ||
185 | static int idtoname_parse(struct cache_detail *, char *, int); | 185 | static int idtoname_parse(struct cache_detail *, char *, int); |
186 | static struct ent *idtoname_lookup(struct ent *); | 186 | static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); |
187 | static struct ent *idtoname_update(struct ent *, struct ent *); | 187 | static struct ent *idtoname_update(struct cache_detail *, struct ent *, |
188 | struct ent *); | ||
188 | 189 | ||
189 | static struct cache_detail idtoname_cache = { | 190 | static 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; |
270 | out: | 270 | out: |
@@ -275,10 +275,9 @@ out: | |||
275 | 275 | ||
276 | 276 | ||
277 | static struct ent * | 277 | static struct ent * |
278 | idtoname_lookup(struct ent *item) | 278 | idtoname_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 | ||
289 | static struct ent * | 288 | static struct ent * |
290 | idtoname_update(struct ent *new, struct ent *old) | 289 | idtoname_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 | ||
306 | static struct cache_head *nametoid_table[ENT_HASHMAX]; | ||
307 | |||
308 | static inline int | 304 | static inline int |
309 | nametoid_hash(struct ent *ent) | 305 | nametoid_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 | ||
362 | static struct ent *nametoid_lookup(struct ent *); | 358 | static struct ent *nametoid_lookup(struct cache_detail *, struct ent *); |
363 | static struct ent *nametoid_update(struct ent *, struct ent *); | 359 | static struct ent *nametoid_update(struct cache_detail *, struct ent *, |
360 | struct ent *); | ||
364 | static int nametoid_parse(struct cache_detail *, char *, int); | 361 | static int nametoid_parse(struct cache_detail *, char *, int); |
365 | 362 | ||
366 | static struct cache_detail nametoid_cache = { | 363 | static 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; |
438 | out: | 434 | out: |
439 | kfree(buf1); | 435 | kfree(buf1); |
@@ -443,10 +439,9 @@ out: | |||
443 | 439 | ||
444 | 440 | ||
445 | static struct ent * | 441 | static struct ent * |
446 | nametoid_lookup(struct ent *item) | 442 | nametoid_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 | ||
457 | static struct ent * | 452 | static struct ent * |
458 | nametoid_update(struct ent *new, struct ent *old) | 453 | nametoid_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 | ||
473 | int | 467 | int |
474 | nfsd_idmap_init(void) | 468 | nfsd_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 | |||
489 | destroy_nametoid_cache: | ||
490 | cache_destroy_net(nn->nametoid_cache, net); | ||
491 | unregister_idtoname_cache: | ||
492 | cache_unregister_net(nn->idtoname_cache, net); | ||
493 | destroy_idtoname_cache: | ||
494 | cache_destroy_net(nn->idtoname_cache, net); | ||
484 | return rv; | 495 | return rv; |
485 | } | 496 | } |
486 | 497 | ||
487 | void | 498 | void |
488 | nfsd_idmap_shutdown(void) | 499 | nfsd_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 | ||
494 | static int | 509 | static int |
495 | idmap_lookup(struct svc_rqst *rqstp, | 510 | idmap_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 | |||
588 | static __be32 | 605 | static __be32 |
589 | do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id) | 606 | do_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 | |||
601 | static int | 618 | static int |
602 | do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | 619 | do_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 | } |