summaryrefslogtreecommitdiffstats
path: root/fs/nfs/idmap.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-08-26 17:16:17 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-09-01 11:12:42 -0400
commit2127d82af302be94066223311ca6ff317ee13ee0 (patch)
tree2230247736de754f98923d235a0cf3938aa91a48 /fs/nfs/idmap.c
parent5f42b016d7341871948a2b8cc8fb654691522d1a (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.c184
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
66struct idmap { 66struct 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
405static void __nfs_idmap_unregister(struct rpc_pipe *pipe) 406static 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
413static int __nfs_idmap_register(struct dentry *dir, 418static 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
426static void nfs_idmap_unregister(struct nfs_client *clp, 432static 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
439static 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
457int 437int
458nfs_idmap_new(struct nfs_client *clp) 438nfs_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;
468err_destroy_pipe:
469 rpc_destroy_pipe_data(idmap->idmap_pipe);
470err:
471 kfree(idmap);
472 return error;
485} 473}
486 474
487void 475void
@@ -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
500static 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
537static 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
544restart:
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
575static 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
597static struct notifier_block nfs_idmap_block = {
598 .notifier_call = rpc_pipefs_event,
599 .priority = SUNRPC_PIPEFS_NFS_PRIO,
600};
601
602int nfs_idmap_init(void) 490int 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();
611out: 496out:
612 return ret; 497 return ret;
613} 498}
614 499
615void nfs_idmap_quit(void) 500void 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