diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/fs/super.c b/fs/super.c index 15f2afdbf82e..8a669f6f3f52 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
231 | if (root) { | 231 | if (root) { |
232 | sb->s_root = NULL; | 232 | sb->s_root = NULL; |
233 | shrink_dcache_parent(root); | 233 | shrink_dcache_parent(root); |
234 | shrink_dcache_anon(&sb->s_anon); | 234 | shrink_dcache_sb(sb); |
235 | dput(root); | 235 | dput(root); |
236 | fsync_super(sb); | 236 | fsync_super(sb); |
237 | lock_super(sb); | 237 | lock_super(sb); |
@@ -486,7 +486,7 @@ asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) | |||
486 | s = user_get_super(new_decode_dev(dev)); | 486 | s = user_get_super(new_decode_dev(dev)); |
487 | if (s == NULL) | 487 | if (s == NULL) |
488 | goto out; | 488 | goto out; |
489 | err = vfs_statfs(s, &sbuf); | 489 | err = vfs_statfs(s->s_root, &sbuf); |
490 | drop_super(s); | 490 | drop_super(s); |
491 | if (err) | 491 | if (err) |
492 | goto out; | 492 | goto out; |
@@ -676,9 +676,10 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action) | |||
676 | } | 676 | } |
677 | } | 677 | } |
678 | 678 | ||
679 | struct super_block *get_sb_bdev(struct file_system_type *fs_type, | 679 | int get_sb_bdev(struct file_system_type *fs_type, |
680 | int flags, const char *dev_name, void *data, | 680 | int flags, const char *dev_name, void *data, |
681 | int (*fill_super)(struct super_block *, void *, int)) | 681 | int (*fill_super)(struct super_block *, void *, int), |
682 | struct vfsmount *mnt) | ||
682 | { | 683 | { |
683 | struct block_device *bdev; | 684 | struct block_device *bdev; |
684 | struct super_block *s; | 685 | struct super_block *s; |
@@ -686,7 +687,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, | |||
686 | 687 | ||
687 | bdev = open_bdev_excl(dev_name, flags, fs_type); | 688 | bdev = open_bdev_excl(dev_name, flags, fs_type); |
688 | if (IS_ERR(bdev)) | 689 | if (IS_ERR(bdev)) |
689 | return (struct super_block *)bdev; | 690 | return PTR_ERR(bdev); |
690 | 691 | ||
691 | /* | 692 | /* |
692 | * once the super is inserted into the list by sget, s_umount | 693 | * once the super is inserted into the list by sget, s_umount |
@@ -697,15 +698,17 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, | |||
697 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); | 698 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); |
698 | mutex_unlock(&bdev->bd_mount_mutex); | 699 | mutex_unlock(&bdev->bd_mount_mutex); |
699 | if (IS_ERR(s)) | 700 | if (IS_ERR(s)) |
700 | goto out; | 701 | goto error_s; |
701 | 702 | ||
702 | if (s->s_root) { | 703 | if (s->s_root) { |
703 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 704 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
704 | up_write(&s->s_umount); | 705 | up_write(&s->s_umount); |
705 | deactivate_super(s); | 706 | deactivate_super(s); |
706 | s = ERR_PTR(-EBUSY); | 707 | error = -EBUSY; |
708 | goto error_bdev; | ||
707 | } | 709 | } |
708 | goto out; | 710 | |
711 | close_bdev_excl(bdev); | ||
709 | } else { | 712 | } else { |
710 | char b[BDEVNAME_SIZE]; | 713 | char b[BDEVNAME_SIZE]; |
711 | 714 | ||
@@ -716,18 +719,21 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, | |||
716 | if (error) { | 719 | if (error) { |
717 | up_write(&s->s_umount); | 720 | up_write(&s->s_umount); |
718 | deactivate_super(s); | 721 | deactivate_super(s); |
719 | s = ERR_PTR(error); | 722 | goto error; |
720 | } else { | ||
721 | s->s_flags |= MS_ACTIVE; | ||
722 | bdev_uevent(bdev, KOBJ_MOUNT); | ||
723 | } | 723 | } |
724 | |||
725 | s->s_flags |= MS_ACTIVE; | ||
726 | bdev_uevent(bdev, KOBJ_MOUNT); | ||
724 | } | 727 | } |
725 | 728 | ||
726 | return s; | 729 | return simple_set_mnt(mnt, s); |
727 | 730 | ||
728 | out: | 731 | error_s: |
732 | error = PTR_ERR(s); | ||
733 | error_bdev: | ||
729 | close_bdev_excl(bdev); | 734 | close_bdev_excl(bdev); |
730 | return s; | 735 | error: |
736 | return error; | ||
731 | } | 737 | } |
732 | 738 | ||
733 | EXPORT_SYMBOL(get_sb_bdev); | 739 | EXPORT_SYMBOL(get_sb_bdev); |
@@ -744,15 +750,16 @@ void kill_block_super(struct super_block *sb) | |||
744 | 750 | ||
745 | EXPORT_SYMBOL(kill_block_super); | 751 | EXPORT_SYMBOL(kill_block_super); |
746 | 752 | ||
747 | struct super_block *get_sb_nodev(struct file_system_type *fs_type, | 753 | int get_sb_nodev(struct file_system_type *fs_type, |
748 | int flags, void *data, | 754 | int flags, void *data, |
749 | int (*fill_super)(struct super_block *, void *, int)) | 755 | int (*fill_super)(struct super_block *, void *, int), |
756 | struct vfsmount *mnt) | ||
750 | { | 757 | { |
751 | int error; | 758 | int error; |
752 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 759 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); |
753 | 760 | ||
754 | if (IS_ERR(s)) | 761 | if (IS_ERR(s)) |
755 | return s; | 762 | return PTR_ERR(s); |
756 | 763 | ||
757 | s->s_flags = flags; | 764 | s->s_flags = flags; |
758 | 765 | ||
@@ -760,10 +767,10 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type, | |||
760 | if (error) { | 767 | if (error) { |
761 | up_write(&s->s_umount); | 768 | up_write(&s->s_umount); |
762 | deactivate_super(s); | 769 | deactivate_super(s); |
763 | return ERR_PTR(error); | 770 | return error; |
764 | } | 771 | } |
765 | s->s_flags |= MS_ACTIVE; | 772 | s->s_flags |= MS_ACTIVE; |
766 | return s; | 773 | return simple_set_mnt(mnt, s); |
767 | } | 774 | } |
768 | 775 | ||
769 | EXPORT_SYMBOL(get_sb_nodev); | 776 | EXPORT_SYMBOL(get_sb_nodev); |
@@ -773,28 +780,29 @@ static int compare_single(struct super_block *s, void *p) | |||
773 | return 1; | 780 | return 1; |
774 | } | 781 | } |
775 | 782 | ||
776 | struct super_block *get_sb_single(struct file_system_type *fs_type, | 783 | int get_sb_single(struct file_system_type *fs_type, |
777 | int flags, void *data, | 784 | int flags, void *data, |
778 | int (*fill_super)(struct super_block *, void *, int)) | 785 | int (*fill_super)(struct super_block *, void *, int), |
786 | struct vfsmount *mnt) | ||
779 | { | 787 | { |
780 | struct super_block *s; | 788 | struct super_block *s; |
781 | int error; | 789 | int error; |
782 | 790 | ||
783 | s = sget(fs_type, compare_single, set_anon_super, NULL); | 791 | s = sget(fs_type, compare_single, set_anon_super, NULL); |
784 | if (IS_ERR(s)) | 792 | if (IS_ERR(s)) |
785 | return s; | 793 | return PTR_ERR(s); |
786 | if (!s->s_root) { | 794 | if (!s->s_root) { |
787 | s->s_flags = flags; | 795 | s->s_flags = flags; |
788 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 796 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
789 | if (error) { | 797 | if (error) { |
790 | up_write(&s->s_umount); | 798 | up_write(&s->s_umount); |
791 | deactivate_super(s); | 799 | deactivate_super(s); |
792 | return ERR_PTR(error); | 800 | return error; |
793 | } | 801 | } |
794 | s->s_flags |= MS_ACTIVE; | 802 | s->s_flags |= MS_ACTIVE; |
795 | } | 803 | } |
796 | do_remount_sb(s, flags, data, 0); | 804 | do_remount_sb(s, flags, data, 0); |
797 | return s; | 805 | return simple_set_mnt(mnt, s); |
798 | } | 806 | } |
799 | 807 | ||
800 | EXPORT_SYMBOL(get_sb_single); | 808 | EXPORT_SYMBOL(get_sb_single); |
@@ -802,52 +810,51 @@ EXPORT_SYMBOL(get_sb_single); | |||
802 | struct vfsmount * | 810 | struct vfsmount * |
803 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) | 811 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) |
804 | { | 812 | { |
805 | struct super_block *sb = ERR_PTR(-ENOMEM); | ||
806 | struct vfsmount *mnt; | 813 | struct vfsmount *mnt; |
807 | int error; | ||
808 | char *secdata = NULL; | 814 | char *secdata = NULL; |
815 | int error; | ||
816 | |||
817 | if (!type) | ||
818 | return ERR_PTR(-ENODEV); | ||
809 | 819 | ||
820 | error = -ENOMEM; | ||
810 | mnt = alloc_vfsmnt(name); | 821 | mnt = alloc_vfsmnt(name); |
811 | if (!mnt) | 822 | if (!mnt) |
812 | goto out; | 823 | goto out; |
813 | 824 | ||
814 | if (data) { | 825 | if (data) { |
815 | secdata = alloc_secdata(); | 826 | secdata = alloc_secdata(); |
816 | if (!secdata) { | 827 | if (!secdata) |
817 | sb = ERR_PTR(-ENOMEM); | ||
818 | goto out_mnt; | 828 | goto out_mnt; |
819 | } | ||
820 | 829 | ||
821 | error = security_sb_copy_data(type, data, secdata); | 830 | error = security_sb_copy_data(type, data, secdata); |
822 | if (error) { | 831 | if (error) |
823 | sb = ERR_PTR(error); | ||
824 | goto out_free_secdata; | 832 | goto out_free_secdata; |
825 | } | ||
826 | } | 833 | } |
827 | 834 | ||
828 | sb = type->get_sb(type, flags, name, data); | 835 | error = type->get_sb(type, flags, name, data, mnt); |
829 | if (IS_ERR(sb)) | 836 | if (error < 0) |
830 | goto out_free_secdata; | 837 | goto out_free_secdata; |
831 | error = security_sb_kern_mount(sb, secdata); | 838 | |
839 | error = security_sb_kern_mount(mnt->mnt_sb, secdata); | ||
832 | if (error) | 840 | if (error) |
833 | goto out_sb; | 841 | goto out_sb; |
834 | mnt->mnt_sb = sb; | 842 | |
835 | mnt->mnt_root = dget(sb->s_root); | 843 | mnt->mnt_mountpoint = mnt->mnt_root; |
836 | mnt->mnt_mountpoint = sb->s_root; | ||
837 | mnt->mnt_parent = mnt; | 844 | mnt->mnt_parent = mnt; |
838 | up_write(&sb->s_umount); | 845 | up_write(&mnt->mnt_sb->s_umount); |
839 | free_secdata(secdata); | 846 | free_secdata(secdata); |
840 | return mnt; | 847 | return mnt; |
841 | out_sb: | 848 | out_sb: |
842 | up_write(&sb->s_umount); | 849 | dput(mnt->mnt_root); |
843 | deactivate_super(sb); | 850 | up_write(&mnt->mnt_sb->s_umount); |
844 | sb = ERR_PTR(error); | 851 | deactivate_super(mnt->mnt_sb); |
845 | out_free_secdata: | 852 | out_free_secdata: |
846 | free_secdata(secdata); | 853 | free_secdata(secdata); |
847 | out_mnt: | 854 | out_mnt: |
848 | free_vfsmnt(mnt); | 855 | free_vfsmnt(mnt); |
849 | out: | 856 | out: |
850 | return (struct vfsmount *)sb; | 857 | return ERR_PTR(error); |
851 | } | 858 | } |
852 | 859 | ||
853 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 860 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |