diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 119 |
1 files changed, 84 insertions, 35 deletions
diff --git a/fs/super.c b/fs/super.c index 8819e3a7ff20..ca696155cd9a 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -273,14 +273,14 @@ void generic_shutdown_super(struct super_block *sb) | |||
273 | get_fs_excl(); | 273 | get_fs_excl(); |
274 | sb->s_flags &= ~MS_ACTIVE; | 274 | sb->s_flags &= ~MS_ACTIVE; |
275 | 275 | ||
276 | /* bad name - it should be evict_inodes() */ | 276 | fsnotify_unmount_inodes(&sb->s_inodes); |
277 | invalidate_inodes(sb); | 277 | |
278 | evict_inodes(sb); | ||
278 | 279 | ||
279 | if (sop->put_super) | 280 | if (sop->put_super) |
280 | sop->put_super(sb); | 281 | sop->put_super(sb); |
281 | 282 | ||
282 | /* Forget any remaining inodes */ | 283 | if (!list_empty(&sb->s_inodes)) { |
283 | if (invalidate_inodes(sb)) { | ||
284 | printk("VFS: Busy inodes after unmount of %s. " | 284 | printk("VFS: Busy inodes after unmount of %s. " |
285 | "Self-destruct in 5 seconds. Have a nice day...\n", | 285 | "Self-destruct in 5 seconds. Have a nice day...\n", |
286 | sb->s_id); | 286 | sb->s_id); |
@@ -715,15 +715,14 @@ static int ns_set_super(struct super_block *sb, void *data) | |||
715 | return set_anon_super(sb, NULL); | 715 | return set_anon_super(sb, NULL); |
716 | } | 716 | } |
717 | 717 | ||
718 | int get_sb_ns(struct file_system_type *fs_type, int flags, void *data, | 718 | struct dentry *mount_ns(struct file_system_type *fs_type, int flags, |
719 | int (*fill_super)(struct super_block *, void *, int), | 719 | void *data, int (*fill_super)(struct super_block *, void *, int)) |
720 | struct vfsmount *mnt) | ||
721 | { | 720 | { |
722 | struct super_block *sb; | 721 | struct super_block *sb; |
723 | 722 | ||
724 | sb = sget(fs_type, ns_test_super, ns_set_super, data); | 723 | sb = sget(fs_type, ns_test_super, ns_set_super, data); |
725 | if (IS_ERR(sb)) | 724 | if (IS_ERR(sb)) |
726 | return PTR_ERR(sb); | 725 | return ERR_CAST(sb); |
727 | 726 | ||
728 | if (!sb->s_root) { | 727 | if (!sb->s_root) { |
729 | int err; | 728 | int err; |
@@ -731,17 +730,16 @@ int get_sb_ns(struct file_system_type *fs_type, int flags, void *data, | |||
731 | err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 730 | err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
732 | if (err) { | 731 | if (err) { |
733 | deactivate_locked_super(sb); | 732 | deactivate_locked_super(sb); |
734 | return err; | 733 | return ERR_PTR(err); |
735 | } | 734 | } |
736 | 735 | ||
737 | sb->s_flags |= MS_ACTIVE; | 736 | sb->s_flags |= MS_ACTIVE; |
738 | } | 737 | } |
739 | 738 | ||
740 | simple_set_mnt(mnt, sb); | 739 | return dget(sb->s_root); |
741 | return 0; | ||
742 | } | 740 | } |
743 | 741 | ||
744 | EXPORT_SYMBOL(get_sb_ns); | 742 | EXPORT_SYMBOL(mount_ns); |
745 | 743 | ||
746 | #ifdef CONFIG_BLOCK | 744 | #ifdef CONFIG_BLOCK |
747 | static int set_bdev_super(struct super_block *s, void *data) | 745 | static int set_bdev_super(struct super_block *s, void *data) |
@@ -762,10 +760,9 @@ static int test_bdev_super(struct super_block *s, void *data) | |||
762 | return (void *)s->s_bdev == data; | 760 | return (void *)s->s_bdev == data; |
763 | } | 761 | } |
764 | 762 | ||
765 | int get_sb_bdev(struct file_system_type *fs_type, | 763 | struct dentry *mount_bdev(struct file_system_type *fs_type, |
766 | int flags, const char *dev_name, void *data, | 764 | int flags, const char *dev_name, void *data, |
767 | int (*fill_super)(struct super_block *, void *, int), | 765 | int (*fill_super)(struct super_block *, void *, int)) |
768 | struct vfsmount *mnt) | ||
769 | { | 766 | { |
770 | struct block_device *bdev; | 767 | struct block_device *bdev; |
771 | struct super_block *s; | 768 | struct super_block *s; |
@@ -777,7 +774,7 @@ int get_sb_bdev(struct file_system_type *fs_type, | |||
777 | 774 | ||
778 | bdev = open_bdev_exclusive(dev_name, mode, fs_type); | 775 | bdev = open_bdev_exclusive(dev_name, mode, fs_type); |
779 | if (IS_ERR(bdev)) | 776 | if (IS_ERR(bdev)) |
780 | return PTR_ERR(bdev); | 777 | return ERR_CAST(bdev); |
781 | 778 | ||
782 | /* | 779 | /* |
783 | * once the super is inserted into the list by sget, s_umount | 780 | * once the super is inserted into the list by sget, s_umount |
@@ -829,15 +826,30 @@ int get_sb_bdev(struct file_system_type *fs_type, | |||
829 | bdev->bd_super = s; | 826 | bdev->bd_super = s; |
830 | } | 827 | } |
831 | 828 | ||
832 | simple_set_mnt(mnt, s); | 829 | return dget(s->s_root); |
833 | return 0; | ||
834 | 830 | ||
835 | error_s: | 831 | error_s: |
836 | error = PTR_ERR(s); | 832 | error = PTR_ERR(s); |
837 | error_bdev: | 833 | error_bdev: |
838 | close_bdev_exclusive(bdev, mode); | 834 | close_bdev_exclusive(bdev, mode); |
839 | error: | 835 | error: |
840 | return error; | 836 | return ERR_PTR(error); |
837 | } | ||
838 | EXPORT_SYMBOL(mount_bdev); | ||
839 | |||
840 | int get_sb_bdev(struct file_system_type *fs_type, | ||
841 | int flags, const char *dev_name, void *data, | ||
842 | int (*fill_super)(struct super_block *, void *, int), | ||
843 | struct vfsmount *mnt) | ||
844 | { | ||
845 | struct dentry *root; | ||
846 | |||
847 | root = mount_bdev(fs_type, flags, dev_name, data, fill_super); | ||
848 | if (IS_ERR(root)) | ||
849 | return PTR_ERR(root); | ||
850 | mnt->mnt_root = root; | ||
851 | mnt->mnt_sb = root->d_sb; | ||
852 | return 0; | ||
841 | } | 853 | } |
842 | 854 | ||
843 | EXPORT_SYMBOL(get_sb_bdev); | 855 | EXPORT_SYMBOL(get_sb_bdev); |
@@ -856,29 +868,42 @@ void kill_block_super(struct super_block *sb) | |||
856 | EXPORT_SYMBOL(kill_block_super); | 868 | EXPORT_SYMBOL(kill_block_super); |
857 | #endif | 869 | #endif |
858 | 870 | ||
859 | int get_sb_nodev(struct file_system_type *fs_type, | 871 | struct dentry *mount_nodev(struct file_system_type *fs_type, |
860 | int flags, void *data, | 872 | int flags, void *data, |
861 | int (*fill_super)(struct super_block *, void *, int), | 873 | int (*fill_super)(struct super_block *, void *, int)) |
862 | struct vfsmount *mnt) | ||
863 | { | 874 | { |
864 | int error; | 875 | int error; |
865 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 876 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); |
866 | 877 | ||
867 | if (IS_ERR(s)) | 878 | if (IS_ERR(s)) |
868 | return PTR_ERR(s); | 879 | return ERR_CAST(s); |
869 | 880 | ||
870 | s->s_flags = flags; | 881 | s->s_flags = flags; |
871 | 882 | ||
872 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 883 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
873 | if (error) { | 884 | if (error) { |
874 | deactivate_locked_super(s); | 885 | deactivate_locked_super(s); |
875 | return error; | 886 | return ERR_PTR(error); |
876 | } | 887 | } |
877 | s->s_flags |= MS_ACTIVE; | 888 | s->s_flags |= MS_ACTIVE; |
878 | simple_set_mnt(mnt, s); | 889 | return dget(s->s_root); |
879 | return 0; | ||
880 | } | 890 | } |
891 | EXPORT_SYMBOL(mount_nodev); | ||
892 | |||
893 | int get_sb_nodev(struct file_system_type *fs_type, | ||
894 | int flags, void *data, | ||
895 | int (*fill_super)(struct super_block *, void *, int), | ||
896 | struct vfsmount *mnt) | ||
897 | { | ||
898 | struct dentry *root; | ||
881 | 899 | ||
900 | root = mount_nodev(fs_type, flags, data, fill_super); | ||
901 | if (IS_ERR(root)) | ||
902 | return PTR_ERR(root); | ||
903 | mnt->mnt_root = root; | ||
904 | mnt->mnt_sb = root->d_sb; | ||
905 | return 0; | ||
906 | } | ||
882 | EXPORT_SYMBOL(get_sb_nodev); | 907 | EXPORT_SYMBOL(get_sb_nodev); |
883 | 908 | ||
884 | static int compare_single(struct super_block *s, void *p) | 909 | static int compare_single(struct super_block *s, void *p) |
@@ -886,29 +911,42 @@ static int compare_single(struct super_block *s, void *p) | |||
886 | return 1; | 911 | return 1; |
887 | } | 912 | } |
888 | 913 | ||
889 | int get_sb_single(struct file_system_type *fs_type, | 914 | struct dentry *mount_single(struct file_system_type *fs_type, |
890 | int flags, void *data, | 915 | int flags, void *data, |
891 | int (*fill_super)(struct super_block *, void *, int), | 916 | int (*fill_super)(struct super_block *, void *, int)) |
892 | struct vfsmount *mnt) | ||
893 | { | 917 | { |
894 | struct super_block *s; | 918 | struct super_block *s; |
895 | int error; | 919 | int error; |
896 | 920 | ||
897 | s = sget(fs_type, compare_single, set_anon_super, NULL); | 921 | s = sget(fs_type, compare_single, set_anon_super, NULL); |
898 | if (IS_ERR(s)) | 922 | if (IS_ERR(s)) |
899 | return PTR_ERR(s); | 923 | return ERR_CAST(s); |
900 | if (!s->s_root) { | 924 | if (!s->s_root) { |
901 | s->s_flags = flags; | 925 | s->s_flags = flags; |
902 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 926 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
903 | if (error) { | 927 | if (error) { |
904 | deactivate_locked_super(s); | 928 | deactivate_locked_super(s); |
905 | return error; | 929 | return ERR_PTR(error); |
906 | } | 930 | } |
907 | s->s_flags |= MS_ACTIVE; | 931 | s->s_flags |= MS_ACTIVE; |
908 | } else { | 932 | } else { |
909 | do_remount_sb(s, flags, data, 0); | 933 | do_remount_sb(s, flags, data, 0); |
910 | } | 934 | } |
911 | simple_set_mnt(mnt, s); | 935 | return dget(s->s_root); |
936 | } | ||
937 | EXPORT_SYMBOL(mount_single); | ||
938 | |||
939 | int get_sb_single(struct file_system_type *fs_type, | ||
940 | int flags, void *data, | ||
941 | int (*fill_super)(struct super_block *, void *, int), | ||
942 | struct vfsmount *mnt) | ||
943 | { | ||
944 | struct dentry *root; | ||
945 | root = mount_single(fs_type, flags, data, fill_super); | ||
946 | if (IS_ERR(root)) | ||
947 | return PTR_ERR(root); | ||
948 | mnt->mnt_root = root; | ||
949 | mnt->mnt_sb = root->d_sb; | ||
912 | return 0; | 950 | return 0; |
913 | } | 951 | } |
914 | 952 | ||
@@ -918,6 +956,7 @@ struct vfsmount * | |||
918 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) | 956 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) |
919 | { | 957 | { |
920 | struct vfsmount *mnt; | 958 | struct vfsmount *mnt; |
959 | struct dentry *root; | ||
921 | char *secdata = NULL; | 960 | char *secdata = NULL; |
922 | int error; | 961 | int error; |
923 | 962 | ||
@@ -942,9 +981,19 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
942 | goto out_free_secdata; | 981 | goto out_free_secdata; |
943 | } | 982 | } |
944 | 983 | ||
945 | error = type->get_sb(type, flags, name, data, mnt); | 984 | if (type->mount) { |
946 | if (error < 0) | 985 | root = type->mount(type, flags, name, data); |
947 | goto out_free_secdata; | 986 | if (IS_ERR(root)) { |
987 | error = PTR_ERR(root); | ||
988 | goto out_free_secdata; | ||
989 | } | ||
990 | mnt->mnt_root = root; | ||
991 | mnt->mnt_sb = root->d_sb; | ||
992 | } else { | ||
993 | error = type->get_sb(type, flags, name, data, mnt); | ||
994 | if (error < 0) | ||
995 | goto out_free_secdata; | ||
996 | } | ||
948 | BUG_ON(!mnt->mnt_sb); | 997 | BUG_ON(!mnt->mnt_sb); |
949 | WARN_ON(!mnt->mnt_sb->s_bdi); | 998 | WARN_ON(!mnt->mnt_sb->s_bdi); |
950 | mnt->mnt_sb->s_flags |= MS_BORN; | 999 | mnt->mnt_sb->s_flags |= MS_BORN; |