diff options
author | Christoph Hellwig <hch@infradead.org> | 2005-07-24 18:53:01 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-09-23 12:38:57 -0400 |
commit | 278c995c8a153bb2a9bc427e931cfb9c8034c9d7 (patch) | |
tree | fe1b62d1686c78659133d751393ab2d5acf38665 /net | |
parent | 470056c288334eb0b37be26c9ff8aee37ed1cc7a (diff) |
[PATCH] RPC,NFS: new rpc_pipefs patch
Currently rpc_mkdir/rpc_rmdir and rpc_mkpipe/mk_unlink have an API that's
a little unfortunate. They take a path relative to the rpc_pipefs root and
thus need to perform a full lookup. If you look at debugfs or usbfs they
always store the dentry for directories they created and thus can pass in
a dentry + single pathname component pair into their equivalents of the
above functions.
And in fact rpc_pipefs actually stores a dentry for all but one component so
this change not only simplifies the core rpc_pipe code but also the callers.
Unfortuntately this code path is only used by the NFS4 idmapper and
AUTH_GSSAPI for which I don't have a test enviroment. Could someone give
it a spin? It's the last bit needed before we can rework the
lookup_hash API
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 9 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 53 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 268 |
3 files changed, 133 insertions, 197 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d2b08f16c257..bd2555139fa9 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -87,7 +87,6 @@ struct gss_auth { | |||
87 | struct list_head upcalls; | 87 | struct list_head upcalls; |
88 | struct rpc_clnt *client; | 88 | struct rpc_clnt *client; |
89 | struct dentry *dentry; | 89 | struct dentry *dentry; |
90 | char path[48]; | ||
91 | spinlock_t lock; | 90 | spinlock_t lock; |
92 | }; | 91 | }; |
93 | 92 | ||
@@ -690,10 +689,8 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
690 | if (err) | 689 | if (err) |
691 | goto err_put_mech; | 690 | goto err_put_mech; |
692 | 691 | ||
693 | snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s", | 692 | gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, |
694 | clnt->cl_pathname, | 693 | clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); |
695 | gss_auth->mech->gm_name); | ||
696 | gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | ||
697 | if (IS_ERR(gss_auth->dentry)) { | 694 | if (IS_ERR(gss_auth->dentry)) { |
698 | err = PTR_ERR(gss_auth->dentry); | 695 | err = PTR_ERR(gss_auth->dentry); |
699 | goto err_put_mech; | 696 | goto err_put_mech; |
@@ -718,7 +715,7 @@ gss_destroy(struct rpc_auth *auth) | |||
718 | auth, auth->au_flavor); | 715 | auth, auth->au_flavor); |
719 | 716 | ||
720 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 717 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
721 | rpc_unlink(gss_auth->path); | 718 | rpc_unlink(gss_auth->dentry); |
722 | gss_mech_put(gss_auth->mech); | 719 | gss_mech_put(gss_auth->mech); |
723 | 720 | ||
724 | rpcauth_free_credcache(auth); | 721 | rpcauth_free_credcache(auth); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 5a8f01d726e9..63bf591310e0 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -67,26 +67,42 @@ static u32 * call_verify(struct rpc_task *task); | |||
67 | static int | 67 | static int |
68 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | 68 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) |
69 | { | 69 | { |
70 | static uint32_t clntid; | 70 | static unsigned int clntid; |
71 | char name[128]; | ||
71 | int error; | 72 | int error; |
72 | 73 | ||
73 | if (dir_name == NULL) | 74 | if (dir_name == NULL) |
74 | return 0; | 75 | return 0; |
75 | for (;;) { | 76 | |
76 | snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname), | 77 | retry_parent: |
77 | "%s/clnt%x", dir_name, | 78 | clnt->__cl_parent_dentry = rpc_mkdir(NULL, dir_name, NULL); |
78 | (unsigned int)clntid++); | 79 | if (IS_ERR(clnt->__cl_parent_dentry)) { |
79 | clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0'; | 80 | error = PTR_ERR(clnt->__cl_parent_dentry); |
80 | clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt); | 81 | if (error == -EEXIST) |
81 | if (!IS_ERR(clnt->cl_dentry)) | 82 | goto retry_parent; /* XXX(hch): WTF? */ |
82 | return 0; | 83 | |
84 | printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", | ||
85 | dir_name, error); | ||
86 | return error; | ||
87 | } | ||
88 | |||
89 | |||
90 | retry_child: | ||
91 | snprintf(name, sizeof(name), "clnt%x", clntid++); | ||
92 | name[sizeof(name) - 1] = '\0'; | ||
93 | |||
94 | clnt->cl_dentry = rpc_mkdir(clnt->__cl_parent_dentry, name, clnt); | ||
95 | if (IS_ERR(clnt->cl_dentry)) { | ||
83 | error = PTR_ERR(clnt->cl_dentry); | 96 | error = PTR_ERR(clnt->cl_dentry); |
84 | if (error != -EEXIST) { | 97 | if (error == -EEXIST) |
85 | printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", | 98 | goto retry_child; |
86 | clnt->cl_pathname, error); | 99 | printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", |
87 | return error; | 100 | name, error); |
88 | } | 101 | rpc_rmdir(clnt->__cl_parent_dentry); |
102 | return error; | ||
89 | } | 103 | } |
104 | |||
105 | return 0; | ||
90 | } | 106 | } |
91 | 107 | ||
92 | /* | 108 | /* |
@@ -174,7 +190,8 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
174 | return clnt; | 190 | return clnt; |
175 | 191 | ||
176 | out_no_auth: | 192 | out_no_auth: |
177 | rpc_rmdir(clnt->cl_pathname); | 193 | rpc_rmdir(clnt->cl_dentry); |
194 | rpc_rmdir(clnt->__cl_parent_dentry); | ||
178 | out_no_path: | 195 | out_no_path: |
179 | if (clnt->cl_server != clnt->cl_inline_name) | 196 | if (clnt->cl_server != clnt->cl_inline_name) |
180 | kfree(clnt->cl_server); | 197 | kfree(clnt->cl_server); |
@@ -302,8 +319,10 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
302 | rpc_destroy_client(clnt->cl_parent); | 319 | rpc_destroy_client(clnt->cl_parent); |
303 | goto out_free; | 320 | goto out_free; |
304 | } | 321 | } |
305 | if (clnt->cl_pathname[0]) | 322 | if (clnt->cl_dentry) |
306 | rpc_rmdir(clnt->cl_pathname); | 323 | rpc_rmdir(clnt->cl_dentry); |
324 | if (clnt->__cl_parent_dentry) | ||
325 | rpc_rmdir(clnt->__cl_parent_dentry); | ||
307 | if (clnt->cl_xprt) { | 326 | if (clnt->cl_xprt) { |
308 | xprt_destroy(clnt->cl_xprt); | 327 | xprt_destroy(clnt->cl_xprt); |
309 | clnt->cl_xprt = NULL; | 328 | clnt->cl_xprt = NULL; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index ded6c63f11ec..b382809726d8 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -414,38 +414,6 @@ rpc_put_mount(void) | |||
414 | simple_release_fs(&rpc_mount, &rpc_mount_count); | 414 | simple_release_fs(&rpc_mount, &rpc_mount_count); |
415 | } | 415 | } |
416 | 416 | ||
417 | static int | ||
418 | rpc_lookup_parent(char *path, struct nameidata *nd) | ||
419 | { | ||
420 | if (path[0] == '\0') | ||
421 | return -ENOENT; | ||
422 | if (rpc_get_mount()) { | ||
423 | printk(KERN_WARNING "%s: %s failed to mount " | ||
424 | "pseudofilesystem \n", __FILE__, __FUNCTION__); | ||
425 | return -ENODEV; | ||
426 | } | ||
427 | nd->mnt = mntget(rpc_mount); | ||
428 | nd->dentry = dget(rpc_mount->mnt_root); | ||
429 | nd->last_type = LAST_ROOT; | ||
430 | nd->flags = LOOKUP_PARENT; | ||
431 | nd->depth = 0; | ||
432 | |||
433 | if (path_walk(path, nd)) { | ||
434 | printk(KERN_WARNING "%s: %s failed to find path %s\n", | ||
435 | __FILE__, __FUNCTION__, path); | ||
436 | rpc_put_mount(); | ||
437 | return -ENOENT; | ||
438 | } | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static void | ||
443 | rpc_release_path(struct nameidata *nd) | ||
444 | { | ||
445 | path_release(nd); | ||
446 | rpc_put_mount(); | ||
447 | } | ||
448 | |||
449 | static struct inode * | 417 | static struct inode * |
450 | rpc_get_inode(struct super_block *sb, int mode) | 418 | rpc_get_inode(struct super_block *sb, int mode) |
451 | { | 419 | { |
@@ -550,197 +518,149 @@ out_bad: | |||
550 | return -ENOMEM; | 518 | return -ENOMEM; |
551 | } | 519 | } |
552 | 520 | ||
553 | static int | 521 | struct dentry * |
554 | __rpc_mkdir(struct inode *dir, struct dentry *dentry) | 522 | rpc_mkdir(struct dentry *parent, char *name, struct rpc_clnt *rpc_client) |
555 | { | 523 | { |
524 | struct inode *dir; | ||
525 | struct dentry *dentry; | ||
556 | struct inode *inode; | 526 | struct inode *inode; |
557 | |||
558 | inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR); | ||
559 | if (!inode) | ||
560 | goto out_err; | ||
561 | inode->i_ino = iunique(dir->i_sb, 100); | ||
562 | d_instantiate(dentry, inode); | ||
563 | dir->i_nlink++; | ||
564 | inode_dir_notify(dir, DN_CREATE); | ||
565 | rpc_get_mount(); | ||
566 | return 0; | ||
567 | out_err: | ||
568 | printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", | ||
569 | __FILE__, __FUNCTION__, dentry->d_name.name); | ||
570 | return -ENOMEM; | ||
571 | } | ||
572 | |||
573 | static int | ||
574 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) | ||
575 | { | ||
576 | int error; | 527 | int error; |
577 | 528 | ||
578 | shrink_dcache_parent(dentry); | 529 | if (!parent) |
579 | if (dentry->d_inode) { | 530 | parent = rpc_mount->mnt_root; |
580 | rpc_close_pipes(dentry->d_inode); | ||
581 | rpc_inode_setowner(dentry->d_inode, NULL); | ||
582 | } | ||
583 | if ((error = simple_rmdir(dir, dentry)) != 0) | ||
584 | return error; | ||
585 | if (!error) { | ||
586 | inode_dir_notify(dir, DN_DELETE); | ||
587 | d_drop(dentry); | ||
588 | rpc_put_mount(); | ||
589 | } | ||
590 | return 0; | ||
591 | } | ||
592 | 531 | ||
593 | static struct dentry * | 532 | dir = parent->d_inode; |
594 | rpc_lookup_negative(char *path, struct nameidata *nd) | 533 | |
595 | { | 534 | error = rpc_get_mount(); |
596 | struct dentry *dentry; | 535 | if (error) |
597 | struct inode *dir; | ||
598 | int error; | ||
599 | |||
600 | if ((error = rpc_lookup_parent(path, nd)) != 0) | ||
601 | return ERR_PTR(error); | 536 | return ERR_PTR(error); |
602 | dir = nd->dentry->d_inode; | 537 | |
603 | down(&dir->i_sem); | 538 | down(&dir->i_sem); |
604 | dentry = lookup_hash(&nd->last, nd->dentry); | 539 | dentry = lookup_one_len(name, parent, strlen(name)); |
605 | if (IS_ERR(dentry)) | 540 | if (IS_ERR(dentry)) |
606 | goto out_err; | 541 | goto out_unlock; |
607 | if (dentry->d_inode) { | 542 | if (dentry->d_inode) { |
608 | dput(dentry); | ||
609 | dentry = ERR_PTR(-EEXIST); | 543 | dentry = ERR_PTR(-EEXIST); |
610 | goto out_err; | 544 | goto out_dput; |
611 | } | 545 | } |
612 | return dentry; | ||
613 | out_err: | ||
614 | up(&dir->i_sem); | ||
615 | rpc_release_path(nd); | ||
616 | return dentry; | ||
617 | } | ||
618 | 546 | ||
547 | inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR); | ||
548 | if (!inode) | ||
549 | goto out_dput; | ||
550 | inode->i_ino = iunique(dir->i_sb, 100); | ||
551 | dir->i_nlink++; | ||
552 | RPC_I(dentry->d_inode)->private = rpc_client; | ||
619 | 553 | ||
620 | struct dentry * | 554 | d_instantiate(dentry, inode); |
621 | rpc_mkdir(char *path, struct rpc_clnt *rpc_client) | 555 | dget(dentry); |
622 | { | 556 | up(&dir->i_sem); |
623 | struct nameidata nd; | 557 | |
624 | struct dentry *dentry; | 558 | inode_dir_notify(dir, DN_CREATE); |
625 | struct inode *dir; | ||
626 | int error; | ||
627 | 559 | ||
628 | dentry = rpc_lookup_negative(path, &nd); | ||
629 | if (IS_ERR(dentry)) | ||
630 | return dentry; | ||
631 | dir = nd.dentry->d_inode; | ||
632 | if ((error = __rpc_mkdir(dir, dentry)) != 0) | ||
633 | goto err_dput; | ||
634 | RPC_I(dentry->d_inode)->private = rpc_client; | ||
635 | error = rpc_populate(dentry, authfiles, | 560 | error = rpc_populate(dentry, authfiles, |
636 | RPCAUTH_info, RPCAUTH_EOF); | 561 | RPCAUTH_info, RPCAUTH_EOF); |
637 | if (error) | 562 | if (error) |
638 | goto err_depopulate; | 563 | goto out_depopulate; |
639 | out: | 564 | |
640 | up(&dir->i_sem); | ||
641 | rpc_release_path(&nd); | ||
642 | return dentry; | 565 | return dentry; |
643 | err_depopulate: | 566 | |
644 | rpc_depopulate(dentry); | 567 | out_depopulate: |
645 | __rpc_rmdir(dir, dentry); | 568 | rpc_rmdir(dentry); |
646 | err_dput: | 569 | out_dput: |
647 | dput(dentry); | 570 | dput(dentry); |
648 | printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n", | 571 | out_unlock: |
649 | __FILE__, __FUNCTION__, path, error); | 572 | up(&dir->i_sem); |
650 | dentry = ERR_PTR(error); | 573 | rpc_put_mount(); |
651 | goto out; | 574 | return dentry; |
652 | } | 575 | } |
653 | 576 | ||
654 | int | 577 | void |
655 | rpc_rmdir(char *path) | 578 | rpc_rmdir(struct dentry *dentry) |
656 | { | 579 | { |
657 | struct nameidata nd; | 580 | struct dentry *parent = dentry->d_parent; |
658 | struct dentry *dentry; | ||
659 | struct inode *dir; | ||
660 | int error; | ||
661 | 581 | ||
662 | if ((error = rpc_lookup_parent(path, &nd)) != 0) | ||
663 | return error; | ||
664 | dir = nd.dentry->d_inode; | ||
665 | down(&dir->i_sem); | ||
666 | dentry = lookup_hash(&nd.last, nd.dentry); | ||
667 | if (IS_ERR(dentry)) { | ||
668 | error = PTR_ERR(dentry); | ||
669 | goto out_release; | ||
670 | } | ||
671 | rpc_depopulate(dentry); | 582 | rpc_depopulate(dentry); |
672 | error = __rpc_rmdir(dir, dentry); | 583 | |
673 | dput(dentry); | 584 | down(&parent->d_inode->i_sem); |
674 | out_release: | 585 | if (dentry->d_inode) { |
675 | up(&dir->i_sem); | 586 | rpc_close_pipes(dentry->d_inode); |
676 | rpc_release_path(&nd); | 587 | rpc_inode_setowner(dentry->d_inode, NULL); |
677 | return error; | 588 | simple_rmdir(parent->d_inode, dentry); |
589 | } | ||
590 | up(&parent->d_inode->i_sem); | ||
591 | |||
592 | inode_dir_notify(parent->d_inode, DN_DELETE); | ||
593 | rpc_put_mount(); | ||
678 | } | 594 | } |
679 | 595 | ||
680 | struct dentry * | 596 | struct dentry * |
681 | rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) | 597 | rpc_mkpipe(struct dentry *parent, char *name, void *private, |
598 | struct rpc_pipe_ops *ops, int flags) | ||
682 | { | 599 | { |
683 | struct nameidata nd; | 600 | struct inode *dir = parent->d_inode; |
684 | struct dentry *dentry; | 601 | struct dentry *dentry; |
685 | struct inode *dir, *inode; | 602 | struct inode *inode; |
686 | struct rpc_inode *rpci; | 603 | struct rpc_inode *rpci; |
604 | int error; | ||
605 | |||
606 | error = rpc_get_mount(); | ||
607 | if (error) | ||
608 | return ERR_PTR(error); | ||
687 | 609 | ||
688 | dentry = rpc_lookup_negative(path, &nd); | 610 | down(&parent->d_inode->i_sem); |
611 | dentry = lookup_one_len(name, parent, strlen(name)); | ||
689 | if (IS_ERR(dentry)) | 612 | if (IS_ERR(dentry)) |
690 | return dentry; | 613 | goto out_unlock; |
691 | dir = nd.dentry->d_inode; | 614 | if (dentry->d_inode) { |
692 | inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR); | 615 | dentry = ERR_PTR(-EEXIST); |
693 | if (!inode) | 616 | goto out_dput; |
694 | goto err_dput; | 617 | } |
618 | |||
619 | inode = rpc_get_inode(parent->d_inode->i_sb, | ||
620 | S_IFSOCK | S_IRUSR | S_IWUSR); | ||
621 | if (!inode) { | ||
622 | dentry = ERR_PTR(-ENOMEM); | ||
623 | goto out_dput; | ||
624 | } | ||
625 | |||
695 | inode->i_ino = iunique(dir->i_sb, 100); | 626 | inode->i_ino = iunique(dir->i_sb, 100); |
696 | inode->i_fop = &rpc_pipe_fops; | 627 | inode->i_fop = &rpc_pipe_fops; |
697 | d_instantiate(dentry, inode); | 628 | |
698 | rpci = RPC_I(inode); | 629 | rpci = RPC_I(inode); |
699 | rpci->private = private; | 630 | rpci->private = private; |
700 | rpci->flags = flags; | 631 | rpci->flags = flags; |
701 | rpci->ops = ops; | 632 | rpci->ops = ops; |
633 | |||
634 | d_instantiate(dentry, inode); | ||
635 | dget(dentry); | ||
636 | up(&parent->d_inode->i_sem); | ||
637 | |||
702 | inode_dir_notify(dir, DN_CREATE); | 638 | inode_dir_notify(dir, DN_CREATE); |
703 | out: | ||
704 | up(&dir->i_sem); | ||
705 | rpc_release_path(&nd); | ||
706 | return dentry; | 639 | return dentry; |
707 | err_dput: | 640 | |
641 | out_dput: | ||
708 | dput(dentry); | 642 | dput(dentry); |
709 | dentry = ERR_PTR(-ENOMEM); | 643 | out_unlock: |
710 | printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n", | 644 | up(&parent->d_inode->i_sem); |
711 | __FILE__, __FUNCTION__, path, -ENOMEM); | 645 | rpc_put_mount(); |
712 | goto out; | 646 | return dentry; |
713 | } | 647 | } |
714 | 648 | ||
715 | int | 649 | void |
716 | rpc_unlink(char *path) | 650 | rpc_unlink(struct dentry *dentry) |
717 | { | 651 | { |
718 | struct nameidata nd; | 652 | struct dentry *parent = dentry->d_parent; |
719 | struct dentry *dentry; | ||
720 | struct inode *dir; | ||
721 | int error; | ||
722 | 653 | ||
723 | if ((error = rpc_lookup_parent(path, &nd)) != 0) | 654 | down(&parent->d_inode->i_sem); |
724 | return error; | ||
725 | dir = nd.dentry->d_inode; | ||
726 | down(&dir->i_sem); | ||
727 | dentry = lookup_hash(&nd.last, nd.dentry); | ||
728 | if (IS_ERR(dentry)) { | ||
729 | error = PTR_ERR(dentry); | ||
730 | goto out_release; | ||
731 | } | ||
732 | d_drop(dentry); | ||
733 | if (dentry->d_inode) { | 655 | if (dentry->d_inode) { |
734 | rpc_close_pipes(dentry->d_inode); | 656 | rpc_close_pipes(dentry->d_inode); |
735 | rpc_inode_setowner(dentry->d_inode, NULL); | 657 | rpc_inode_setowner(dentry->d_inode, NULL); |
736 | error = simple_unlink(dir, dentry); | 658 | simple_unlink(parent->d_inode, dentry); |
737 | } | 659 | } |
738 | dput(dentry); | 660 | up(&parent->d_inode->i_sem); |
739 | inode_dir_notify(dir, DN_DELETE); | 661 | |
740 | out_release: | 662 | inode_dir_notify(parent->d_inode, DN_DELETE); |
741 | up(&dir->i_sem); | 663 | rpc_put_mount(); |
742 | rpc_release_path(&nd); | ||
743 | return error; | ||
744 | } | 664 | } |
745 | 665 | ||
746 | /* | 666 | /* |