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/sunrpc/rpc_pipe.c | |
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/sunrpc/rpc_pipe.c')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 268 |
1 files changed, 94 insertions, 174 deletions
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 | /* |