diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 187 |
1 files changed, 101 insertions, 86 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 36338515f342..e5f37ded1565 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -401,7 +401,6 @@ static const struct file_operations rpc_info_operations = { | |||
401 | * We have a single directory with 1 node in it. | 401 | * We have a single directory with 1 node in it. |
402 | */ | 402 | */ |
403 | enum { | 403 | enum { |
404 | RPCAUTH_Root = 1, | ||
405 | RPCAUTH_lockd, | 404 | RPCAUTH_lockd, |
406 | RPCAUTH_mount, | 405 | RPCAUTH_mount, |
407 | RPCAUTH_nfs, | 406 | RPCAUTH_nfs, |
@@ -415,12 +414,12 @@ enum { | |||
415 | * Description of fs contents. | 414 | * Description of fs contents. |
416 | */ | 415 | */ |
417 | struct rpc_filelist { | 416 | struct rpc_filelist { |
418 | char *name; | 417 | const char *name; |
419 | const struct file_operations *i_fop; | 418 | const struct file_operations *i_fop; |
420 | umode_t mode; | 419 | umode_t mode; |
421 | }; | 420 | }; |
422 | 421 | ||
423 | static struct rpc_filelist files[] = { | 422 | static const struct rpc_filelist files[] = { |
424 | [RPCAUTH_lockd] = { | 423 | [RPCAUTH_lockd] = { |
425 | .name = "lockd", | 424 | .name = "lockd", |
426 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, | 425 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, |
@@ -448,11 +447,11 @@ static struct rpc_filelist files[] = { | |||
448 | }; | 447 | }; |
449 | 448 | ||
450 | enum { | 449 | enum { |
451 | RPCAUTH_info = 2, | 450 | RPCAUTH_info, |
452 | RPCAUTH_EOF | 451 | RPCAUTH_EOF |
453 | }; | 452 | }; |
454 | 453 | ||
455 | static struct rpc_filelist authfiles[] = { | 454 | static const struct rpc_filelist authfiles[] = { |
456 | [RPCAUTH_info] = { | 455 | [RPCAUTH_info] = { |
457 | .name = "info", | 456 | .name = "info", |
458 | .i_fop = &rpc_info_operations, | 457 | .i_fop = &rpc_info_operations, |
@@ -564,6 +563,20 @@ out_err: | |||
564 | return -ENOMEM; | 563 | return -ENOMEM; |
565 | } | 564 | } |
566 | 565 | ||
566 | static int __rpc_create(struct inode *dir, struct dentry *dentry, | ||
567 | umode_t mode, | ||
568 | const struct file_operations *i_fop, | ||
569 | void *private) | ||
570 | { | ||
571 | int err; | ||
572 | |||
573 | err = __rpc_create_common(dir, dentry, S_IFREG | mode, i_fop, private); | ||
574 | if (err) | ||
575 | return err; | ||
576 | fsnotify_create(dir, dentry); | ||
577 | return 0; | ||
578 | } | ||
579 | |||
567 | static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, | 580 | static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, |
568 | umode_t mode, | 581 | umode_t mode, |
569 | const struct file_operations *i_fop, | 582 | const struct file_operations *i_fop, |
@@ -601,6 +614,17 @@ static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, | |||
601 | return 0; | 614 | return 0; |
602 | } | 615 | } |
603 | 616 | ||
617 | static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) | ||
618 | { | ||
619 | int ret; | ||
620 | |||
621 | dget(dentry); | ||
622 | ret = simple_rmdir(dir, dentry); | ||
623 | d_delete(dentry); | ||
624 | dput(dentry); | ||
625 | return ret; | ||
626 | } | ||
627 | |||
604 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | 628 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) |
605 | { | 629 | { |
606 | int ret; | 630 | int ret; |
@@ -678,100 +702,96 @@ static struct dentry *rpc_lookup_negative(const char *path, | |||
678 | /* | 702 | /* |
679 | * FIXME: This probably has races. | 703 | * FIXME: This probably has races. |
680 | */ | 704 | */ |
681 | static void rpc_depopulate(struct dentry *parent, | 705 | static void __rpc_depopulate(struct dentry *parent, |
682 | unsigned long start, unsigned long eof) | 706 | const struct rpc_filelist *files, |
707 | int start, int eof) | ||
683 | { | 708 | { |
684 | struct inode *dir = parent->d_inode; | 709 | struct inode *dir = parent->d_inode; |
685 | struct list_head *pos, *next; | 710 | struct dentry *dentry; |
686 | struct dentry *dentry, *dvec[10]; | 711 | struct qstr name; |
687 | int n = 0; | 712 | int i; |
688 | 713 | ||
689 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD); | 714 | for (i = start; i < eof; i++) { |
690 | repeat: | 715 | name.name = files[i].name; |
691 | spin_lock(&dcache_lock); | 716 | name.len = strlen(files[i].name); |
692 | list_for_each_safe(pos, next, &parent->d_subdirs) { | 717 | name.hash = full_name_hash(name.name, name.len); |
693 | dentry = list_entry(pos, struct dentry, d_u.d_child); | 718 | dentry = d_lookup(parent, &name); |
694 | if (!dentry->d_inode || | 719 | |
695 | dentry->d_inode->i_ino < start || | 720 | if (dentry == NULL) |
696 | dentry->d_inode->i_ino >= eof) | ||
697 | continue; | 721 | continue; |
698 | spin_lock(&dentry->d_lock); | 722 | if (dentry->d_inode == NULL) |
699 | if (!d_unhashed(dentry)) { | 723 | goto next; |
700 | dget_locked(dentry); | 724 | switch (dentry->d_inode->i_mode & S_IFMT) { |
701 | __d_drop(dentry); | 725 | default: |
702 | spin_unlock(&dentry->d_lock); | 726 | BUG(); |
703 | dvec[n++] = dentry; | 727 | case S_IFREG: |
704 | if (n == ARRAY_SIZE(dvec)) | 728 | __rpc_unlink(dir, dentry); |
705 | break; | 729 | break; |
706 | } else | 730 | case S_IFDIR: |
707 | spin_unlock(&dentry->d_lock); | 731 | __rpc_rmdir(dir, dentry); |
708 | } | 732 | } |
709 | spin_unlock(&dcache_lock); | 733 | next: |
710 | if (n) { | 734 | dput(dentry); |
711 | do { | ||
712 | dentry = dvec[--n]; | ||
713 | if (S_ISREG(dentry->d_inode->i_mode)) | ||
714 | simple_unlink(dir, dentry); | ||
715 | else if (S_ISDIR(dentry->d_inode->i_mode)) | ||
716 | simple_rmdir(dir, dentry); | ||
717 | d_delete(dentry); | ||
718 | dput(dentry); | ||
719 | } while (n); | ||
720 | goto repeat; | ||
721 | } | 735 | } |
736 | } | ||
737 | |||
738 | static void rpc_depopulate(struct dentry *parent, | ||
739 | const struct rpc_filelist *files, | ||
740 | int start, int eof) | ||
741 | { | ||
742 | struct inode *dir = parent->d_inode; | ||
743 | |||
744 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD); | ||
745 | __rpc_depopulate(parent, files, start, eof); | ||
722 | mutex_unlock(&dir->i_mutex); | 746 | mutex_unlock(&dir->i_mutex); |
723 | } | 747 | } |
724 | 748 | ||
725 | static int | 749 | static int rpc_populate(struct dentry *parent, |
726 | rpc_populate(struct dentry *parent, | 750 | const struct rpc_filelist *files, |
727 | struct rpc_filelist *files, | 751 | int start, int eof, |
728 | int start, int eof) | 752 | void *private) |
729 | { | 753 | { |
730 | struct inode *inode, *dir = parent->d_inode; | 754 | struct inode *dir = parent->d_inode; |
731 | void *private = RPC_I(dir)->private; | ||
732 | struct dentry *dentry; | 755 | struct dentry *dentry; |
733 | umode_t mode; | 756 | int i, err; |
734 | int i; | ||
735 | 757 | ||
736 | mutex_lock(&dir->i_mutex); | 758 | mutex_lock(&dir->i_mutex); |
737 | for (i = start; i < eof; i++) { | 759 | for (i = start; i < eof; i++) { |
738 | dentry = d_alloc_name(parent, files[i].name); | 760 | struct qstr q; |
739 | if (!dentry) | 761 | |
740 | goto out_bad; | 762 | q.name = files[i].name; |
741 | dentry->d_op = &rpc_dentry_operations; | 763 | q.len = strlen(files[i].name); |
742 | mode = files[i].mode; | 764 | q.hash = full_name_hash(q.name, q.len); |
743 | inode = rpc_get_inode(dir->i_sb, mode); | 765 | dentry = __rpc_lookup_create_exclusive(parent, &q); |
744 | if (!inode) { | 766 | err = PTR_ERR(dentry); |
745 | dput(dentry); | 767 | if (IS_ERR(dentry)) |
746 | goto out_bad; | 768 | goto out_bad; |
769 | switch (files[i].mode & S_IFMT) { | ||
770 | default: | ||
771 | BUG(); | ||
772 | case S_IFREG: | ||
773 | err = __rpc_create(dir, dentry, | ||
774 | files[i].mode, | ||
775 | files[i].i_fop, | ||
776 | private); | ||
777 | break; | ||
778 | case S_IFDIR: | ||
779 | err = __rpc_mkdir(dir, dentry, | ||
780 | files[i].mode, | ||
781 | NULL, | ||
782 | private); | ||
747 | } | 783 | } |
748 | inode->i_ino = i; | 784 | if (err != 0) |
749 | if (files[i].i_fop) | 785 | goto out_bad; |
750 | inode->i_fop = files[i].i_fop; | ||
751 | if (private) | ||
752 | rpc_inode_setowner(inode, private); | ||
753 | if (S_ISDIR(mode)) | ||
754 | inc_nlink(dir); | ||
755 | d_add(dentry, inode); | ||
756 | fsnotify_create(dir, dentry); | ||
757 | } | 786 | } |
758 | mutex_unlock(&dir->i_mutex); | 787 | mutex_unlock(&dir->i_mutex); |
759 | return 0; | 788 | return 0; |
760 | out_bad: | 789 | out_bad: |
790 | __rpc_depopulate(parent, files, start, eof); | ||
761 | mutex_unlock(&dir->i_mutex); | 791 | mutex_unlock(&dir->i_mutex); |
762 | printk(KERN_WARNING "%s: %s failed to populate directory %s\n", | 792 | printk(KERN_WARNING "%s: %s failed to populate directory %s\n", |
763 | __FILE__, __func__, parent->d_name.name); | 793 | __FILE__, __func__, parent->d_name.name); |
764 | return -ENOMEM; | 794 | return err; |
765 | } | ||
766 | |||
767 | static int | ||
768 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) | ||
769 | { | ||
770 | int error; | ||
771 | error = simple_rmdir(dir, dentry); | ||
772 | if (!error) | ||
773 | d_delete(dentry); | ||
774 | return error; | ||
775 | } | 795 | } |
776 | 796 | ||
777 | /** | 797 | /** |
@@ -800,16 +820,14 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) | |||
800 | if (error != 0) | 820 | if (error != 0) |
801 | goto out_err; | 821 | goto out_err; |
802 | error = rpc_populate(dentry, authfiles, | 822 | error = rpc_populate(dentry, authfiles, |
803 | RPCAUTH_info, RPCAUTH_EOF); | 823 | RPCAUTH_info, RPCAUTH_EOF, rpc_client); |
804 | if (error) | 824 | if (error) |
805 | goto err_depopulate; | 825 | goto err_rmdir; |
806 | dget(dentry); | ||
807 | out: | 826 | out: |
808 | mutex_unlock(&dir->i_mutex); | 827 | mutex_unlock(&dir->i_mutex); |
809 | rpc_release_path(&nd); | 828 | rpc_release_path(&nd); |
810 | return dentry; | 829 | return dentry; |
811 | err_depopulate: | 830 | err_rmdir: |
812 | rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); | ||
813 | __rpc_rmdir(dir, dentry); | 831 | __rpc_rmdir(dir, dentry); |
814 | out_err: | 832 | out_err: |
815 | printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n", | 833 | printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n", |
@@ -832,9 +850,8 @@ rpc_rmdir(struct dentry *dentry) | |||
832 | parent = dget_parent(dentry); | 850 | parent = dget_parent(dentry); |
833 | dir = parent->d_inode; | 851 | dir = parent->d_inode; |
834 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 852 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
835 | rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); | 853 | rpc_depopulate(dentry, authfiles, RPCAUTH_info, RPCAUTH_EOF); |
836 | error = __rpc_rmdir(dir, dentry); | 854 | error = __rpc_rmdir(dir, dentry); |
837 | dput(dentry); | ||
838 | mutex_unlock(&dir->i_mutex); | 855 | mutex_unlock(&dir->i_mutex); |
839 | dput(parent); | 856 | dput(parent); |
840 | return error; | 857 | return error; |
@@ -900,7 +917,6 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | |||
900 | private, ops, flags); | 917 | private, ops, flags); |
901 | if (err) | 918 | if (err) |
902 | goto out_err; | 919 | goto out_err; |
903 | dget(dentry); | ||
904 | out: | 920 | out: |
905 | mutex_unlock(&dir->i_mutex); | 921 | mutex_unlock(&dir->i_mutex); |
906 | return dentry; | 922 | return dentry; |
@@ -932,7 +948,6 @@ rpc_unlink(struct dentry *dentry) | |||
932 | dir = parent->d_inode; | 948 | dir = parent->d_inode; |
933 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 949 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
934 | error = __rpc_rmpipe(dir, dentry); | 950 | error = __rpc_rmpipe(dir, dentry); |
935 | dput(dentry); | ||
936 | mutex_unlock(&dir->i_mutex); | 951 | mutex_unlock(&dir->i_mutex); |
937 | dput(parent); | 952 | dput(parent); |
938 | return error; | 953 | return error; |
@@ -970,7 +985,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
970 | iput(inode); | 985 | iput(inode); |
971 | return -ENOMEM; | 986 | return -ENOMEM; |
972 | } | 987 | } |
973 | if (rpc_populate(root, files, RPCAUTH_Root + 1, RPCAUTH_RootEOF)) | 988 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
974 | goto out; | 989 | goto out; |
975 | sb->s_root = root; | 990 | sb->s_root = root; |
976 | return 0; | 991 | return 0; |