diff options
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 256 |
1 files changed, 93 insertions, 163 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6989b03e97ab..1777a3467bd2 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -65,9 +65,8 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
65 | "(NILFS)"); | 65 | "(NILFS)"); |
66 | MODULE_LICENSE("GPL"); | 66 | MODULE_LICENSE("GPL"); |
67 | 67 | ||
68 | static void nilfs_write_super(struct super_block *sb); | ||
68 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 69 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
69 | static int test_exclusive_mount(struct file_system_type *fs_type, | ||
70 | struct block_device *bdev, int flags); | ||
71 | 70 | ||
72 | /** | 71 | /** |
73 | * nilfs_error() - report failure condition on a filesystem | 72 | * nilfs_error() - report failure condition on a filesystem |
@@ -315,6 +314,11 @@ static void nilfs_put_super(struct super_block *sb) | |||
315 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 314 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
316 | struct the_nilfs *nilfs = sbi->s_nilfs; | 315 | struct the_nilfs *nilfs = sbi->s_nilfs; |
317 | 316 | ||
317 | lock_kernel(); | ||
318 | |||
319 | if (sb->s_dirt) | ||
320 | nilfs_write_super(sb); | ||
321 | |||
318 | nilfs_detach_segment_constructor(sbi); | 322 | nilfs_detach_segment_constructor(sbi); |
319 | 323 | ||
320 | if (!(sb->s_flags & MS_RDONLY)) { | 324 | if (!(sb->s_flags & MS_RDONLY)) { |
@@ -323,12 +327,18 @@ static void nilfs_put_super(struct super_block *sb) | |||
323 | nilfs_commit_super(sbi, 1); | 327 | nilfs_commit_super(sbi, 1); |
324 | up_write(&nilfs->ns_sem); | 328 | up_write(&nilfs->ns_sem); |
325 | } | 329 | } |
330 | down_write(&nilfs->ns_super_sem); | ||
331 | if (nilfs->ns_current == sbi) | ||
332 | nilfs->ns_current = NULL; | ||
333 | up_write(&nilfs->ns_super_sem); | ||
326 | 334 | ||
327 | nilfs_detach_checkpoint(sbi); | 335 | nilfs_detach_checkpoint(sbi); |
328 | put_nilfs(sbi->s_nilfs); | 336 | put_nilfs(sbi->s_nilfs); |
329 | sbi->s_super = NULL; | 337 | sbi->s_super = NULL; |
330 | sb->s_fs_info = NULL; | 338 | sb->s_fs_info = NULL; |
331 | kfree(sbi); | 339 | nilfs_put_sbinfo(sbi); |
340 | |||
341 | unlock_kernel(); | ||
332 | } | 342 | } |
333 | 343 | ||
334 | /** | 344 | /** |
@@ -383,6 +393,8 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
383 | { | 393 | { |
384 | int err = 0; | 394 | int err = 0; |
385 | 395 | ||
396 | nilfs_write_super(sb); | ||
397 | |||
386 | /* This function is called when super block should be written back */ | 398 | /* This function is called when super block should be written back */ |
387 | if (wait) | 399 | if (wait) |
388 | err = nilfs_construct_segment(sb); | 400 | err = nilfs_construct_segment(sb); |
@@ -396,9 +408,9 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
396 | struct buffer_head *bh_cp; | 408 | struct buffer_head *bh_cp; |
397 | int err; | 409 | int err; |
398 | 410 | ||
399 | down_write(&nilfs->ns_sem); | 411 | down_write(&nilfs->ns_super_sem); |
400 | list_add(&sbi->s_list, &nilfs->ns_supers); | 412 | list_add(&sbi->s_list, &nilfs->ns_supers); |
401 | up_write(&nilfs->ns_sem); | 413 | up_write(&nilfs->ns_super_sem); |
402 | 414 | ||
403 | sbi->s_ifile = nilfs_mdt_new( | 415 | sbi->s_ifile = nilfs_mdt_new( |
404 | nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP); | 416 | nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP); |
@@ -436,9 +448,9 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
436 | nilfs_mdt_destroy(sbi->s_ifile); | 448 | nilfs_mdt_destroy(sbi->s_ifile); |
437 | sbi->s_ifile = NULL; | 449 | sbi->s_ifile = NULL; |
438 | 450 | ||
439 | down_write(&nilfs->ns_sem); | 451 | down_write(&nilfs->ns_super_sem); |
440 | list_del_init(&sbi->s_list); | 452 | list_del_init(&sbi->s_list); |
441 | up_write(&nilfs->ns_sem); | 453 | up_write(&nilfs->ns_super_sem); |
442 | 454 | ||
443 | return err; | 455 | return err; |
444 | } | 456 | } |
@@ -450,9 +462,9 @@ void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) | |||
450 | nilfs_mdt_clear(sbi->s_ifile); | 462 | nilfs_mdt_clear(sbi->s_ifile); |
451 | nilfs_mdt_destroy(sbi->s_ifile); | 463 | nilfs_mdt_destroy(sbi->s_ifile); |
452 | sbi->s_ifile = NULL; | 464 | sbi->s_ifile = NULL; |
453 | down_write(&nilfs->ns_sem); | 465 | down_write(&nilfs->ns_super_sem); |
454 | list_del_init(&sbi->s_list); | 466 | list_del_init(&sbi->s_list); |
455 | up_write(&nilfs->ns_sem); | 467 | up_write(&nilfs->ns_super_sem); |
456 | } | 468 | } |
457 | 469 | ||
458 | static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi) | 470 | static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi) |
@@ -752,7 +764,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
752 | * @silent: silent mode flag | 764 | * @silent: silent mode flag |
753 | * @nilfs: the_nilfs struct | 765 | * @nilfs: the_nilfs struct |
754 | * | 766 | * |
755 | * This function is called exclusively by bd_mount_mutex. | 767 | * This function is called exclusively by nilfs->ns_mount_mutex. |
756 | * So, the recovery process is protected from other simultaneous mounts. | 768 | * So, the recovery process is protected from other simultaneous mounts. |
757 | */ | 769 | */ |
758 | static int | 770 | static int |
@@ -773,6 +785,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
773 | get_nilfs(nilfs); | 785 | get_nilfs(nilfs); |
774 | sbi->s_nilfs = nilfs; | 786 | sbi->s_nilfs = nilfs; |
775 | sbi->s_super = sb; | 787 | sbi->s_super = sb; |
788 | atomic_set(&sbi->s_count, 1); | ||
776 | 789 | ||
777 | err = init_nilfs(nilfs, sbi, (char *)data); | 790 | err = init_nilfs(nilfs, sbi, (char *)data); |
778 | if (err) | 791 | if (err) |
@@ -870,6 +883,11 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
870 | goto failed_root; | 883 | goto failed_root; |
871 | } | 884 | } |
872 | 885 | ||
886 | down_write(&nilfs->ns_super_sem); | ||
887 | if (!nilfs_test_opt(sbi, SNAPSHOT)) | ||
888 | nilfs->ns_current = sbi; | ||
889 | up_write(&nilfs->ns_super_sem); | ||
890 | |||
873 | return 0; | 891 | return 0; |
874 | 892 | ||
875 | failed_root: | 893 | failed_root: |
@@ -885,7 +903,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
885 | failed_sbi: | 903 | failed_sbi: |
886 | put_nilfs(nilfs); | 904 | put_nilfs(nilfs); |
887 | sb->s_fs_info = NULL; | 905 | sb->s_fs_info = NULL; |
888 | kfree(sbi); | 906 | nilfs_put_sbinfo(sbi); |
889 | return err; | 907 | return err; |
890 | } | 908 | } |
891 | 909 | ||
@@ -898,6 +916,9 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
898 | struct nilfs_mount_options old_opts; | 916 | struct nilfs_mount_options old_opts; |
899 | int err; | 917 | int err; |
900 | 918 | ||
919 | lock_kernel(); | ||
920 | |||
921 | down_write(&nilfs->ns_super_sem); | ||
901 | old_sb_flags = sb->s_flags; | 922 | old_sb_flags = sb->s_flags; |
902 | old_opts.mount_opt = sbi->s_mount_opt; | 923 | old_opts.mount_opt = sbi->s_mount_opt; |
903 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | 924 | old_opts.snapshot_cno = sbi->s_snapshot_cno; |
@@ -945,14 +966,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
945 | * store the current valid flag. (It may have been changed | 966 | * store the current valid flag. (It may have been changed |
946 | * by fsck since we originally mounted the partition.) | 967 | * by fsck since we originally mounted the partition.) |
947 | */ | 968 | */ |
948 | down(&sb->s_bdev->bd_mount_sem); | 969 | if (nilfs->ns_current && nilfs->ns_current != sbi) { |
949 | /* Check existing RW-mount */ | ||
950 | if (test_exclusive_mount(sb->s_type, sb->s_bdev, 0)) { | ||
951 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 970 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
952 | "remount because a RW-mount exists.\n", | 971 | "remount because an RW-mount exists.\n", |
953 | sb->s_id); | 972 | sb->s_id); |
954 | err = -EBUSY; | 973 | err = -EBUSY; |
955 | goto rw_remount_failed; | 974 | goto restore_opts; |
956 | } | 975 | } |
957 | if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { | 976 | if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { |
958 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 977 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
@@ -960,7 +979,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
960 | "the latest one.\n", | 979 | "the latest one.\n", |
961 | sb->s_id); | 980 | sb->s_id); |
962 | err = -EINVAL; | 981 | err = -EINVAL; |
963 | goto rw_remount_failed; | 982 | goto restore_opts; |
964 | } | 983 | } |
965 | sb->s_flags &= ~MS_RDONLY; | 984 | sb->s_flags &= ~MS_RDONLY; |
966 | nilfs_clear_opt(sbi, SNAPSHOT); | 985 | nilfs_clear_opt(sbi, SNAPSHOT); |
@@ -968,28 +987,31 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
968 | 987 | ||
969 | err = nilfs_attach_segment_constructor(sbi); | 988 | err = nilfs_attach_segment_constructor(sbi); |
970 | if (err) | 989 | if (err) |
971 | goto rw_remount_failed; | 990 | goto restore_opts; |
972 | 991 | ||
973 | down_write(&nilfs->ns_sem); | 992 | down_write(&nilfs->ns_sem); |
974 | nilfs_setup_super(sbi); | 993 | nilfs_setup_super(sbi); |
975 | up_write(&nilfs->ns_sem); | 994 | up_write(&nilfs->ns_sem); |
976 | 995 | ||
977 | up(&sb->s_bdev->bd_mount_sem); | 996 | nilfs->ns_current = sbi; |
978 | } | 997 | } |
979 | out: | 998 | out: |
999 | up_write(&nilfs->ns_super_sem); | ||
1000 | unlock_kernel(); | ||
980 | return 0; | 1001 | return 0; |
981 | 1002 | ||
982 | rw_remount_failed: | ||
983 | up(&sb->s_bdev->bd_mount_sem); | ||
984 | restore_opts: | 1003 | restore_opts: |
985 | sb->s_flags = old_sb_flags; | 1004 | sb->s_flags = old_sb_flags; |
986 | sbi->s_mount_opt = old_opts.mount_opt; | 1005 | sbi->s_mount_opt = old_opts.mount_opt; |
987 | sbi->s_snapshot_cno = old_opts.snapshot_cno; | 1006 | sbi->s_snapshot_cno = old_opts.snapshot_cno; |
1007 | up_write(&nilfs->ns_super_sem); | ||
1008 | unlock_kernel(); | ||
988 | return err; | 1009 | return err; |
989 | } | 1010 | } |
990 | 1011 | ||
991 | struct nilfs_super_data { | 1012 | struct nilfs_super_data { |
992 | struct block_device *bdev; | 1013 | struct block_device *bdev; |
1014 | struct nilfs_sb_info *sbi; | ||
993 | __u64 cno; | 1015 | __u64 cno; |
994 | int flags; | 1016 | int flags; |
995 | }; | 1017 | }; |
@@ -1048,33 +1070,7 @@ static int nilfs_test_bdev_super(struct super_block *s, void *data) | |||
1048 | { | 1070 | { |
1049 | struct nilfs_super_data *sd = data; | 1071 | struct nilfs_super_data *sd = data; |
1050 | 1072 | ||
1051 | return s->s_bdev == sd->bdev; | 1073 | return sd->sbi && s->s_fs_info == (void *)sd->sbi; |
1052 | } | ||
1053 | |||
1054 | static int nilfs_test_bdev_super2(struct super_block *s, void *data) | ||
1055 | { | ||
1056 | struct nilfs_super_data *sd = data; | ||
1057 | int ret; | ||
1058 | |||
1059 | if (s->s_bdev != sd->bdev) | ||
1060 | return 0; | ||
1061 | |||
1062 | if (!((s->s_flags | sd->flags) & MS_RDONLY)) | ||
1063 | return 1; /* Reuse an old R/W-mode super_block */ | ||
1064 | |||
1065 | if (s->s_flags & sd->flags & MS_RDONLY) { | ||
1066 | if (down_read_trylock(&s->s_umount)) { | ||
1067 | ret = s->s_root && | ||
1068 | (sd->cno == NILFS_SB(s)->s_snapshot_cno); | ||
1069 | up_read(&s->s_umount); | ||
1070 | /* | ||
1071 | * This path is locked with sb_lock by sget(). | ||
1072 | * So, drop_super() causes deadlock. | ||
1073 | */ | ||
1074 | return ret; | ||
1075 | } | ||
1076 | } | ||
1077 | return 0; | ||
1078 | } | 1074 | } |
1079 | 1075 | ||
1080 | static int | 1076 | static int |
@@ -1082,8 +1078,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1082 | const char *dev_name, void *data, struct vfsmount *mnt) | 1078 | const char *dev_name, void *data, struct vfsmount *mnt) |
1083 | { | 1079 | { |
1084 | struct nilfs_super_data sd; | 1080 | struct nilfs_super_data sd; |
1085 | struct super_block *s, *s2; | 1081 | struct super_block *s; |
1086 | struct the_nilfs *nilfs = NULL; | 1082 | struct the_nilfs *nilfs; |
1087 | int err, need_to_close = 1; | 1083 | int err, need_to_close = 1; |
1088 | 1084 | ||
1089 | sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); | 1085 | sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); |
@@ -1095,7 +1091,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1095 | * much more information than normal filesystems to identify mount | 1091 | * much more information than normal filesystems to identify mount |
1096 | * instance. For snapshot mounts, not only a mount type (ro-mount | 1092 | * instance. For snapshot mounts, not only a mount type (ro-mount |
1097 | * or rw-mount) but also a checkpoint number is required. | 1093 | * or rw-mount) but also a checkpoint number is required. |
1098 | * The results are passed in sget() using nilfs_super_data. | ||
1099 | */ | 1094 | */ |
1100 | sd.cno = 0; | 1095 | sd.cno = 0; |
1101 | sd.flags = flags; | 1096 | sd.flags = flags; |
@@ -1104,64 +1099,59 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1104 | goto failed; | 1099 | goto failed; |
1105 | } | 1100 | } |
1106 | 1101 | ||
1107 | /* | 1102 | nilfs = find_or_create_nilfs(sd.bdev); |
1108 | * once the super is inserted into the list by sget, s_umount | 1103 | if (!nilfs) { |
1109 | * will protect the lockfs code from trying to start a snapshot | 1104 | err = -ENOMEM; |
1110 | * while we are mounting | 1105 | goto failed; |
1111 | */ | ||
1112 | down(&sd.bdev->bd_mount_sem); | ||
1113 | if (!sd.cno && | ||
1114 | (err = test_exclusive_mount(fs_type, sd.bdev, flags ^ MS_RDONLY))) { | ||
1115 | err = (err < 0) ? : -EBUSY; | ||
1116 | goto failed_unlock; | ||
1117 | } | 1106 | } |
1118 | 1107 | ||
1119 | /* | 1108 | mutex_lock(&nilfs->ns_mount_mutex); |
1120 | * Phase-1: search any existent instance and get the_nilfs | ||
1121 | */ | ||
1122 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | ||
1123 | if (IS_ERR(s)) | ||
1124 | goto error_s; | ||
1125 | |||
1126 | if (!s->s_root) { | ||
1127 | err = -ENOMEM; | ||
1128 | nilfs = alloc_nilfs(sd.bdev); | ||
1129 | if (!nilfs) | ||
1130 | goto cancel_new; | ||
1131 | } else { | ||
1132 | struct nilfs_sb_info *sbi = NILFS_SB(s); | ||
1133 | 1109 | ||
1110 | if (!sd.cno) { | ||
1134 | /* | 1111 | /* |
1135 | * s_umount protects super_block from unmount process; | 1112 | * Check if an exclusive mount exists or not. |
1136 | * It covers pointers of nilfs_sb_info and the_nilfs. | 1113 | * Snapshot mounts coexist with a current mount |
1114 | * (i.e. rw-mount or ro-mount), whereas rw-mount and | ||
1115 | * ro-mount are mutually exclusive. | ||
1137 | */ | 1116 | */ |
1138 | nilfs = sbi->s_nilfs; | 1117 | down_read(&nilfs->ns_super_sem); |
1139 | get_nilfs(nilfs); | 1118 | if (nilfs->ns_current && |
1140 | up_write(&s->s_umount); | 1119 | ((nilfs->ns_current->s_super->s_flags ^ flags) |
1120 | & MS_RDONLY)) { | ||
1121 | up_read(&nilfs->ns_super_sem); | ||
1122 | err = -EBUSY; | ||
1123 | goto failed_unlock; | ||
1124 | } | ||
1125 | up_read(&nilfs->ns_super_sem); | ||
1126 | } | ||
1141 | 1127 | ||
1142 | /* | 1128 | /* |
1143 | * Phase-2: search specified snapshot or R/W mode super_block | 1129 | * Find existing nilfs_sb_info struct |
1144 | */ | 1130 | */ |
1145 | if (!sd.cno) | 1131 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); |
1146 | /* trying to get the latest checkpoint. */ | ||
1147 | sd.cno = nilfs_last_cno(nilfs); | ||
1148 | 1132 | ||
1149 | s2 = sget(fs_type, nilfs_test_bdev_super2, | 1133 | if (!sd.cno) |
1150 | nilfs_set_bdev_super, &sd); | 1134 | /* trying to get the latest checkpoint. */ |
1151 | deactivate_super(s); | 1135 | sd.cno = nilfs_last_cno(nilfs); |
1152 | /* | 1136 | |
1153 | * Although deactivate_super() invokes close_bdev_exclusive() at | 1137 | /* |
1154 | * kill_block_super(). Here, s is an existent mount; we need | 1138 | * Get super block instance holding the nilfs_sb_info struct. |
1155 | * one more close_bdev_exclusive() call. | 1139 | * A new instance is allocated if no existing mount is present or |
1156 | */ | 1140 | * existing instance has been unmounted. |
1157 | s = s2; | 1141 | */ |
1158 | if (IS_ERR(s)) | 1142 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); |
1159 | goto error_s; | 1143 | if (sd.sbi) |
1144 | nilfs_put_sbinfo(sd.sbi); | ||
1145 | |||
1146 | if (IS_ERR(s)) { | ||
1147 | err = PTR_ERR(s); | ||
1148 | goto failed_unlock; | ||
1160 | } | 1149 | } |
1161 | 1150 | ||
1162 | if (!s->s_root) { | 1151 | if (!s->s_root) { |
1163 | char b[BDEVNAME_SIZE]; | 1152 | char b[BDEVNAME_SIZE]; |
1164 | 1153 | ||
1154 | /* New superblock instance created */ | ||
1165 | s->s_flags = flags; | 1155 | s->s_flags = flags; |
1166 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); | 1156 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); |
1167 | sb_set_blocksize(s, block_size(sd.bdev)); | 1157 | sb_set_blocksize(s, block_size(sd.bdev)); |
@@ -1172,26 +1162,18 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1172 | 1162 | ||
1173 | s->s_flags |= MS_ACTIVE; | 1163 | s->s_flags |= MS_ACTIVE; |
1174 | need_to_close = 0; | 1164 | need_to_close = 0; |
1175 | } else if (!(s->s_flags & MS_RDONLY)) { | ||
1176 | err = -EBUSY; | ||
1177 | } | 1165 | } |
1178 | 1166 | ||
1179 | up(&sd.bdev->bd_mount_sem); | 1167 | mutex_unlock(&nilfs->ns_mount_mutex); |
1180 | put_nilfs(nilfs); | 1168 | put_nilfs(nilfs); |
1181 | if (need_to_close) | 1169 | if (need_to_close) |
1182 | close_bdev_exclusive(sd.bdev, flags); | 1170 | close_bdev_exclusive(sd.bdev, flags); |
1183 | simple_set_mnt(mnt, s); | 1171 | simple_set_mnt(mnt, s); |
1184 | return 0; | 1172 | return 0; |
1185 | 1173 | ||
1186 | error_s: | ||
1187 | up(&sd.bdev->bd_mount_sem); | ||
1188 | if (nilfs) | ||
1189 | put_nilfs(nilfs); | ||
1190 | close_bdev_exclusive(sd.bdev, flags); | ||
1191 | return PTR_ERR(s); | ||
1192 | |||
1193 | failed_unlock: | 1174 | failed_unlock: |
1194 | up(&sd.bdev->bd_mount_sem); | 1175 | mutex_unlock(&nilfs->ns_mount_mutex); |
1176 | put_nilfs(nilfs); | ||
1195 | failed: | 1177 | failed: |
1196 | close_bdev_exclusive(sd.bdev, flags); | 1178 | close_bdev_exclusive(sd.bdev, flags); |
1197 | 1179 | ||
@@ -1199,70 +1181,18 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1199 | 1181 | ||
1200 | cancel_new: | 1182 | cancel_new: |
1201 | /* Abandoning the newly allocated superblock */ | 1183 | /* Abandoning the newly allocated superblock */ |
1202 | up(&sd.bdev->bd_mount_sem); | 1184 | mutex_unlock(&nilfs->ns_mount_mutex); |
1203 | if (nilfs) | 1185 | put_nilfs(nilfs); |
1204 | put_nilfs(nilfs); | ||
1205 | up_write(&s->s_umount); | 1186 | up_write(&s->s_umount); |
1206 | deactivate_super(s); | 1187 | deactivate_super(s); |
1207 | /* | 1188 | /* |
1208 | * deactivate_super() invokes close_bdev_exclusive(). | 1189 | * deactivate_super() invokes close_bdev_exclusive(). |
1209 | * We must finish all post-cleaning before this call; | 1190 | * We must finish all post-cleaning before this call; |
1210 | * put_nilfs() and unlocking bd_mount_sem need the block device. | 1191 | * put_nilfs() needs the block device. |
1211 | */ | 1192 | */ |
1212 | return err; | 1193 | return err; |
1213 | } | 1194 | } |
1214 | 1195 | ||
1215 | static int nilfs_test_bdev_super3(struct super_block *s, void *data) | ||
1216 | { | ||
1217 | struct nilfs_super_data *sd = data; | ||
1218 | int ret; | ||
1219 | |||
1220 | if (s->s_bdev != sd->bdev) | ||
1221 | return 0; | ||
1222 | if (down_read_trylock(&s->s_umount)) { | ||
1223 | ret = (s->s_flags & MS_RDONLY) && s->s_root && | ||
1224 | nilfs_test_opt(NILFS_SB(s), SNAPSHOT); | ||
1225 | up_read(&s->s_umount); | ||
1226 | if (ret) | ||
1227 | return 0; /* ignore snapshot mounts */ | ||
1228 | } | ||
1229 | return !((sd->flags ^ s->s_flags) & MS_RDONLY); | ||
1230 | } | ||
1231 | |||
1232 | static int __false_bdev_super(struct super_block *s, void *data) | ||
1233 | { | ||
1234 | #if 0 /* XXX: workaround for lock debug. This is not good idea */ | ||
1235 | up_write(&s->s_umount); | ||
1236 | #endif | ||
1237 | return -EFAULT; | ||
1238 | } | ||
1239 | |||
1240 | /** | ||
1241 | * test_exclusive_mount - check whether an exclusive RW/RO mount exists or not. | ||
1242 | * fs_type: filesystem type | ||
1243 | * bdev: block device | ||
1244 | * flag: 0 (check rw-mount) or MS_RDONLY (check ro-mount) | ||
1245 | * res: pointer to an integer to store result | ||
1246 | * | ||
1247 | * This function must be called within a section protected by bd_mount_mutex. | ||
1248 | */ | ||
1249 | static int test_exclusive_mount(struct file_system_type *fs_type, | ||
1250 | struct block_device *bdev, int flags) | ||
1251 | { | ||
1252 | struct super_block *s; | ||
1253 | struct nilfs_super_data sd = { .flags = flags, .bdev = bdev }; | ||
1254 | |||
1255 | s = sget(fs_type, nilfs_test_bdev_super3, __false_bdev_super, &sd); | ||
1256 | if (IS_ERR(s)) { | ||
1257 | if (PTR_ERR(s) != -EFAULT) | ||
1258 | return PTR_ERR(s); | ||
1259 | return 0; /* Not found */ | ||
1260 | } | ||
1261 | up_write(&s->s_umount); | ||
1262 | deactivate_super(s); | ||
1263 | return 1; /* Found */ | ||
1264 | } | ||
1265 | |||
1266 | struct file_system_type nilfs_fs_type = { | 1196 | struct file_system_type nilfs_fs_type = { |
1267 | .owner = THIS_MODULE, | 1197 | .owner = THIS_MODULE, |
1268 | .name = "nilfs2", | 1198 | .name = "nilfs2", |