diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-08-26 17:16:17 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-01 11:12:42 -0400 |
commit | 2127d82af302be94066223311ca6ff317ee13ee0 (patch) | |
tree | 2230247736de754f98923d235a0cf3938aa91a48 /fs/nfs/idmap.c | |
parent | 5f42b016d7341871948a2b8cc8fb654691522d1a (diff) |
NFSv4: Convert idmapper to use the new framework for pipefs dentries
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r-- | fs/nfs/idmap.c | 184 |
1 files changed, 34 insertions, 150 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 8b7e94ac096b..567983d2c0eb 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -64,6 +64,7 @@ struct idmap_legacy_upcalldata { | |||
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct idmap { | 66 | struct idmap { |
67 | struct rpc_pipe_dir_object idmap_pdo; | ||
67 | struct rpc_pipe *idmap_pipe; | 68 | struct rpc_pipe *idmap_pipe; |
68 | struct idmap_legacy_upcalldata *idmap_upcall_data; | 69 | struct idmap_legacy_upcalldata *idmap_upcall_data; |
69 | struct mutex idmap_mutex; | 70 | struct mutex idmap_mutex; |
@@ -402,18 +403,23 @@ static struct key_type key_type_id_resolver_legacy = { | |||
402 | .request_key = nfs_idmap_legacy_upcall, | 403 | .request_key = nfs_idmap_legacy_upcall, |
403 | }; | 404 | }; |
404 | 405 | ||
405 | static void __nfs_idmap_unregister(struct rpc_pipe *pipe) | 406 | static void nfs_idmap_pipe_destroy(struct dentry *dir, |
407 | struct rpc_pipe_dir_object *pdo) | ||
406 | { | 408 | { |
409 | struct idmap *idmap = pdo->pdo_data; | ||
410 | struct rpc_pipe *pipe = idmap->idmap_pipe; | ||
411 | |||
407 | if (pipe->dentry) { | 412 | if (pipe->dentry) { |
408 | rpc_unlink(pipe->dentry); | 413 | rpc_unlink(pipe->dentry); |
409 | pipe->dentry = NULL; | 414 | pipe->dentry = NULL; |
410 | } | 415 | } |
411 | } | 416 | } |
412 | 417 | ||
413 | static int __nfs_idmap_register(struct dentry *dir, | 418 | static int nfs_idmap_pipe_create(struct dentry *dir, |
414 | struct idmap *idmap, | 419 | struct rpc_pipe_dir_object *pdo) |
415 | struct rpc_pipe *pipe) | ||
416 | { | 420 | { |
421 | struct idmap *idmap = pdo->pdo_data; | ||
422 | struct rpc_pipe *pipe = idmap->idmap_pipe; | ||
417 | struct dentry *dentry; | 423 | struct dentry *dentry; |
418 | 424 | ||
419 | dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe); | 425 | dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe); |
@@ -423,36 +429,10 @@ static int __nfs_idmap_register(struct dentry *dir, | |||
423 | return 0; | 429 | return 0; |
424 | } | 430 | } |
425 | 431 | ||
426 | static void nfs_idmap_unregister(struct nfs_client *clp, | 432 | static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = { |
427 | struct rpc_pipe *pipe) | 433 | .create = nfs_idmap_pipe_create, |
428 | { | 434 | .destroy = nfs_idmap_pipe_destroy, |
429 | struct net *net = clp->cl_net; | 435 | }; |
430 | struct super_block *pipefs_sb; | ||
431 | |||
432 | pipefs_sb = rpc_get_sb_net(net); | ||
433 | if (pipefs_sb) { | ||
434 | __nfs_idmap_unregister(pipe); | ||
435 | rpc_put_sb_net(net); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | static int nfs_idmap_register(struct nfs_client *clp, | ||
440 | struct idmap *idmap, | ||
441 | struct rpc_pipe *pipe) | ||
442 | { | ||
443 | struct net *net = clp->cl_net; | ||
444 | struct super_block *pipefs_sb; | ||
445 | int err = 0; | ||
446 | |||
447 | pipefs_sb = rpc_get_sb_net(net); | ||
448 | if (pipefs_sb) { | ||
449 | if (clp->cl_rpcclient->cl_dentry) | ||
450 | err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, | ||
451 | idmap, pipe); | ||
452 | rpc_put_sb_net(net); | ||
453 | } | ||
454 | return err; | ||
455 | } | ||
456 | 436 | ||
457 | int | 437 | int |
458 | nfs_idmap_new(struct nfs_client *clp) | 438 | nfs_idmap_new(struct nfs_client *clp) |
@@ -465,23 +445,31 @@ nfs_idmap_new(struct nfs_client *clp) | |||
465 | if (idmap == NULL) | 445 | if (idmap == NULL) |
466 | return -ENOMEM; | 446 | return -ENOMEM; |
467 | 447 | ||
448 | rpc_init_pipe_dir_object(&idmap->idmap_pdo, | ||
449 | &nfs_idmap_pipe_dir_object_ops, | ||
450 | idmap); | ||
451 | |||
468 | pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0); | 452 | pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0); |
469 | if (IS_ERR(pipe)) { | 453 | if (IS_ERR(pipe)) { |
470 | error = PTR_ERR(pipe); | 454 | error = PTR_ERR(pipe); |
471 | kfree(idmap); | 455 | goto err; |
472 | return error; | ||
473 | } | ||
474 | error = nfs_idmap_register(clp, idmap, pipe); | ||
475 | if (error) { | ||
476 | rpc_destroy_pipe_data(pipe); | ||
477 | kfree(idmap); | ||
478 | return error; | ||
479 | } | 456 | } |
480 | idmap->idmap_pipe = pipe; | 457 | idmap->idmap_pipe = pipe; |
481 | mutex_init(&idmap->idmap_mutex); | 458 | mutex_init(&idmap->idmap_mutex); |
482 | 459 | ||
460 | error = rpc_add_pipe_dir_object(clp->cl_net, | ||
461 | &clp->cl_rpcclient->cl_pipedir_objects, | ||
462 | &idmap->idmap_pdo); | ||
463 | if (error) | ||
464 | goto err_destroy_pipe; | ||
465 | |||
483 | clp->cl_idmap = idmap; | 466 | clp->cl_idmap = idmap; |
484 | return 0; | 467 | return 0; |
468 | err_destroy_pipe: | ||
469 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
470 | err: | ||
471 | kfree(idmap); | ||
472 | return error; | ||
485 | } | 473 | } |
486 | 474 | ||
487 | void | 475 | void |
@@ -491,130 +479,26 @@ nfs_idmap_delete(struct nfs_client *clp) | |||
491 | 479 | ||
492 | if (!idmap) | 480 | if (!idmap) |
493 | return; | 481 | return; |
494 | nfs_idmap_unregister(clp, idmap->idmap_pipe); | ||
495 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
496 | clp->cl_idmap = NULL; | 482 | clp->cl_idmap = NULL; |
483 | rpc_remove_pipe_dir_object(clp->cl_net, | ||
484 | &clp->cl_rpcclient->cl_pipedir_objects, | ||
485 | &idmap->idmap_pdo); | ||
486 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
497 | kfree(idmap); | 487 | kfree(idmap); |
498 | } | 488 | } |
499 | 489 | ||
500 | static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event, | ||
501 | struct super_block *sb) | ||
502 | { | ||
503 | int err = 0; | ||
504 | |||
505 | switch (event) { | ||
506 | case RPC_PIPEFS_MOUNT: | ||
507 | err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, | ||
508 | clp->cl_idmap, | ||
509 | clp->cl_idmap->idmap_pipe); | ||
510 | break; | ||
511 | case RPC_PIPEFS_UMOUNT: | ||
512 | if (clp->cl_idmap->idmap_pipe) { | ||
513 | struct dentry *parent; | ||
514 | |||
515 | parent = clp->cl_idmap->idmap_pipe->dentry->d_parent; | ||
516 | __nfs_idmap_unregister(clp->cl_idmap->idmap_pipe); | ||
517 | /* | ||
518 | * Note: This is a dirty hack. SUNRPC hook has been | ||
519 | * called already but simple_rmdir() call for the | ||
520 | * directory returned with error because of idmap pipe | ||
521 | * inside. Thus now we have to remove this directory | ||
522 | * here. | ||
523 | */ | ||
524 | if (rpc_rmdir(parent)) | ||
525 | printk(KERN_ERR "NFS: %s: failed to remove " | ||
526 | "clnt dir!\n", __func__); | ||
527 | } | ||
528 | break; | ||
529 | default: | ||
530 | printk(KERN_ERR "NFS: %s: unknown event: %ld\n", __func__, | ||
531 | event); | ||
532 | return -ENOTSUPP; | ||
533 | } | ||
534 | return err; | ||
535 | } | ||
536 | |||
537 | static struct nfs_client *nfs_get_client_for_event(struct net *net, int event) | ||
538 | { | ||
539 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
540 | struct dentry *cl_dentry; | ||
541 | struct nfs_client *clp; | ||
542 | int err; | ||
543 | |||
544 | restart: | ||
545 | spin_lock(&nn->nfs_client_lock); | ||
546 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | ||
547 | /* Wait for initialisation to finish */ | ||
548 | if (clp->cl_cons_state == NFS_CS_INITING) { | ||
549 | atomic_inc(&clp->cl_count); | ||
550 | spin_unlock(&nn->nfs_client_lock); | ||
551 | err = nfs_wait_client_init_complete(clp); | ||
552 | nfs_put_client(clp); | ||
553 | if (err) | ||
554 | return NULL; | ||
555 | goto restart; | ||
556 | } | ||
557 | /* Skip nfs_clients that failed to initialise */ | ||
558 | if (clp->cl_cons_state < 0) | ||
559 | continue; | ||
560 | smp_rmb(); | ||
561 | if (clp->rpc_ops != &nfs_v4_clientops) | ||
562 | continue; | ||
563 | cl_dentry = clp->cl_idmap->idmap_pipe->dentry; | ||
564 | if (((event == RPC_PIPEFS_MOUNT) && cl_dentry) || | ||
565 | ((event == RPC_PIPEFS_UMOUNT) && !cl_dentry)) | ||
566 | continue; | ||
567 | atomic_inc(&clp->cl_count); | ||
568 | spin_unlock(&nn->nfs_client_lock); | ||
569 | return clp; | ||
570 | } | ||
571 | spin_unlock(&nn->nfs_client_lock); | ||
572 | return NULL; | ||
573 | } | ||
574 | |||
575 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | ||
576 | void *ptr) | ||
577 | { | ||
578 | struct super_block *sb = ptr; | ||
579 | struct nfs_client *clp; | ||
580 | int error = 0; | ||
581 | |||
582 | if (!try_module_get(THIS_MODULE)) | ||
583 | return 0; | ||
584 | |||
585 | while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) { | ||
586 | error = __rpc_pipefs_event(clp, event, sb); | ||
587 | nfs_put_client(clp); | ||
588 | if (error) | ||
589 | break; | ||
590 | } | ||
591 | module_put(THIS_MODULE); | ||
592 | return error; | ||
593 | } | ||
594 | |||
595 | #define PIPEFS_NFS_PRIO 1 | ||
596 | |||
597 | static struct notifier_block nfs_idmap_block = { | ||
598 | .notifier_call = rpc_pipefs_event, | ||
599 | .priority = SUNRPC_PIPEFS_NFS_PRIO, | ||
600 | }; | ||
601 | |||
602 | int nfs_idmap_init(void) | 490 | int nfs_idmap_init(void) |
603 | { | 491 | { |
604 | int ret; | 492 | int ret; |
605 | ret = nfs_idmap_init_keyring(); | 493 | ret = nfs_idmap_init_keyring(); |
606 | if (ret != 0) | 494 | if (ret != 0) |
607 | goto out; | 495 | goto out; |
608 | ret = rpc_pipefs_notifier_register(&nfs_idmap_block); | ||
609 | if (ret != 0) | ||
610 | nfs_idmap_quit_keyring(); | ||
611 | out: | 496 | out: |
612 | return ret; | 497 | return ret; |
613 | } | 498 | } |
614 | 499 | ||
615 | void nfs_idmap_quit(void) | 500 | void nfs_idmap_quit(void) |
616 | { | 501 | { |
617 | rpc_pipefs_notifier_unregister(&nfs_idmap_block); | ||
618 | nfs_idmap_quit_keyring(); | 502 | nfs_idmap_quit_keyring(); |
619 | } | 503 | } |
620 | 504 | ||