diff options
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 80 |
1 files changed, 19 insertions, 61 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1c505d0e031e..3c9833e3e74a 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -1061,13 +1061,6 @@ static int nilfs_set_bdev_super(struct super_block *s, void *data) | |||
1061 | static int nilfs_test_bdev_super(struct super_block *s, void *data) | 1061 | static int nilfs_test_bdev_super(struct super_block *s, void *data) |
1062 | { | 1062 | { |
1063 | struct nilfs_super_data *sd = data; | 1063 | struct nilfs_super_data *sd = data; |
1064 | |||
1065 | return s->s_bdev == sd->bdev; | ||
1066 | } | ||
1067 | |||
1068 | static int nilfs_test_bdev_super2(struct super_block *s, void *data) | ||
1069 | { | ||
1070 | struct nilfs_super_data *sd = data; | ||
1071 | int ret; | 1064 | int ret; |
1072 | 1065 | ||
1073 | if (s->s_bdev != sd->bdev) | 1066 | if (s->s_bdev != sd->bdev) |
@@ -1096,8 +1089,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1096 | const char *dev_name, void *data, struct vfsmount *mnt) | 1089 | const char *dev_name, void *data, struct vfsmount *mnt) |
1097 | { | 1090 | { |
1098 | struct nilfs_super_data sd; | 1091 | struct nilfs_super_data sd; |
1099 | struct super_block *s, *s2; | 1092 | struct super_block *s; |
1100 | struct the_nilfs *nilfs = NULL; | 1093 | struct the_nilfs *nilfs; |
1101 | int err, need_to_close = 1; | 1094 | int err, need_to_close = 1; |
1102 | 1095 | ||
1103 | sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); | 1096 | sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); |
@@ -1118,11 +1111,12 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1118 | goto failed; | 1111 | goto failed; |
1119 | } | 1112 | } |
1120 | 1113 | ||
1121 | /* | 1114 | nilfs = find_or_create_nilfs(sd.bdev); |
1122 | * once the super is inserted into the list by sget, s_umount | 1115 | if (!nilfs) { |
1123 | * will protect the lockfs code from trying to start a snapshot | 1116 | err = -ENOMEM; |
1124 | * while we are mounting | 1117 | goto failed; |
1125 | */ | 1118 | } |
1119 | |||
1126 | down(&sd.bdev->bd_mount_sem); | 1120 | down(&sd.bdev->bd_mount_sem); |
1127 | if (!sd.cno && | 1121 | if (!sd.cno && |
1128 | (err = test_exclusive_mount(fs_type, sd.bdev, flags ^ MS_RDONLY))) { | 1122 | (err = test_exclusive_mount(fs_type, sd.bdev, flags ^ MS_RDONLY))) { |
@@ -1131,51 +1125,22 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1131 | } | 1125 | } |
1132 | 1126 | ||
1133 | /* | 1127 | /* |
1134 | * Phase-1: search any existent instance and get the_nilfs | 1128 | * Search specified snapshot or R/W mode super_block |
1135 | */ | 1129 | */ |
1136 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | 1130 | if (!sd.cno) |
1137 | if (IS_ERR(s)) | 1131 | /* trying to get the latest checkpoint. */ |
1138 | goto error_s; | 1132 | sd.cno = nilfs_last_cno(nilfs); |
1139 | |||
1140 | if (!s->s_root) { | ||
1141 | err = -ENOMEM; | ||
1142 | nilfs = alloc_nilfs(sd.bdev); | ||
1143 | if (!nilfs) | ||
1144 | goto cancel_new; | ||
1145 | } else { | ||
1146 | struct nilfs_sb_info *sbi = NILFS_SB(s); | ||
1147 | 1133 | ||
1148 | /* | 1134 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); |
1149 | * s_umount protects super_block from unmount process; | 1135 | if (IS_ERR(s)) { |
1150 | * It covers pointers of nilfs_sb_info and the_nilfs. | 1136 | err = PTR_ERR(s); |
1151 | */ | 1137 | goto failed_unlock; |
1152 | nilfs = sbi->s_nilfs; | ||
1153 | get_nilfs(nilfs); | ||
1154 | up_write(&s->s_umount); | ||
1155 | |||
1156 | /* | ||
1157 | * Phase-2: search specified snapshot or R/W mode super_block | ||
1158 | */ | ||
1159 | if (!sd.cno) | ||
1160 | /* trying to get the latest checkpoint. */ | ||
1161 | sd.cno = nilfs_last_cno(nilfs); | ||
1162 | |||
1163 | s2 = sget(fs_type, nilfs_test_bdev_super2, | ||
1164 | nilfs_set_bdev_super, &sd); | ||
1165 | deactivate_super(s); | ||
1166 | /* | ||
1167 | * Although deactivate_super() invokes close_bdev_exclusive() at | ||
1168 | * kill_block_super(). Here, s is an existent mount; we need | ||
1169 | * one more close_bdev_exclusive() call. | ||
1170 | */ | ||
1171 | s = s2; | ||
1172 | if (IS_ERR(s)) | ||
1173 | goto error_s; | ||
1174 | } | 1138 | } |
1175 | 1139 | ||
1176 | if (!s->s_root) { | 1140 | if (!s->s_root) { |
1177 | char b[BDEVNAME_SIZE]; | 1141 | char b[BDEVNAME_SIZE]; |
1178 | 1142 | ||
1143 | /* New superblock instance created */ | ||
1179 | s->s_flags = flags; | 1144 | s->s_flags = flags; |
1180 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); | 1145 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); |
1181 | sb_set_blocksize(s, block_size(sd.bdev)); | 1146 | sb_set_blocksize(s, block_size(sd.bdev)); |
@@ -1195,15 +1160,9 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1195 | simple_set_mnt(mnt, s); | 1160 | simple_set_mnt(mnt, s); |
1196 | return 0; | 1161 | return 0; |
1197 | 1162 | ||
1198 | error_s: | ||
1199 | up(&sd.bdev->bd_mount_sem); | ||
1200 | if (nilfs) | ||
1201 | put_nilfs(nilfs); | ||
1202 | close_bdev_exclusive(sd.bdev, flags); | ||
1203 | return PTR_ERR(s); | ||
1204 | |||
1205 | failed_unlock: | 1163 | failed_unlock: |
1206 | up(&sd.bdev->bd_mount_sem); | 1164 | up(&sd.bdev->bd_mount_sem); |
1165 | put_nilfs(nilfs); | ||
1207 | failed: | 1166 | failed: |
1208 | close_bdev_exclusive(sd.bdev, flags); | 1167 | close_bdev_exclusive(sd.bdev, flags); |
1209 | 1168 | ||
@@ -1212,8 +1171,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1212 | cancel_new: | 1171 | cancel_new: |
1213 | /* Abandoning the newly allocated superblock */ | 1172 | /* Abandoning the newly allocated superblock */ |
1214 | up(&sd.bdev->bd_mount_sem); | 1173 | up(&sd.bdev->bd_mount_sem); |
1215 | if (nilfs) | 1174 | put_nilfs(nilfs); |
1216 | put_nilfs(nilfs); | ||
1217 | up_write(&s->s_umount); | 1175 | up_write(&s->s_umount); |
1218 | deactivate_super(s); | 1176 | deactivate_super(s); |
1219 | /* | 1177 | /* |