diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2016-03-23 20:05:27 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2016-04-15 11:49:47 -0400 |
commit | df728b0f6954c38545f4bf12dedeeb9e07469a94 (patch) | |
tree | f7cbf73658f73afd742e80866e266e852a5293ef /fs/f2fs/super.c | |
parent | f2353d7bd4221dfe0e230c5be49038d4a57d97e9 (diff) |
f2fs: recover superblock at RW remounts
This patch adds a sbi flag, SBI_NEED_SB_WRITE, which indicates it needs to
recover superblock when (re)mounting as RW. This is set only when f2fs is
mounted as RO.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/super.c')
-rw-r--r-- | fs/f2fs/super.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index ffe4616376ca..f5fbbfdb3d93 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -796,6 +796,15 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
796 | set_sbi_flag(sbi, SBI_IS_DIRTY); | 796 | set_sbi_flag(sbi, SBI_IS_DIRTY); |
797 | } | 797 | } |
798 | 798 | ||
799 | /* recover superblocks we couldn't write due to previous RO mount */ | ||
800 | if (!(*flags & MS_RDONLY) && is_sbi_flag_set(sbi, SBI_NEED_SB_WRITE)) { | ||
801 | err = f2fs_commit_super(sbi, false); | ||
802 | f2fs_msg(sb, KERN_INFO, | ||
803 | "Try to recover all the superblocks, ret: %d", err); | ||
804 | if (!err) | ||
805 | clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); | ||
806 | } | ||
807 | |||
799 | sync_filesystem(sb); | 808 | sync_filesystem(sb); |
800 | 809 | ||
801 | sbi->mount_opt.opt = 0; | 810 | sbi->mount_opt.opt = 0; |
@@ -852,8 +861,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) | |||
852 | } | 861 | } |
853 | skip: | 862 | skip: |
854 | /* Update the POSIXACL Flag */ | 863 | /* Update the POSIXACL Flag */ |
855 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | | 864 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | |
856 | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); | 865 | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); |
866 | |||
857 | return 0; | 867 | return 0; |
858 | restore_gc: | 868 | restore_gc: |
859 | if (need_restart_gc) { | 869 | if (need_restart_gc) { |
@@ -998,11 +1008,12 @@ static int __f2fs_commit_super(struct buffer_head *bh, | |||
998 | return __sync_dirty_buffer(bh, WRITE_FLUSH_FUA); | 1008 | return __sync_dirty_buffer(bh, WRITE_FLUSH_FUA); |
999 | } | 1009 | } |
1000 | 1010 | ||
1001 | static inline bool sanity_check_area_boundary(struct super_block *sb, | 1011 | static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, |
1002 | struct buffer_head *bh) | 1012 | struct buffer_head *bh) |
1003 | { | 1013 | { |
1004 | struct f2fs_super_block *raw_super = (struct f2fs_super_block *) | 1014 | struct f2fs_super_block *raw_super = (struct f2fs_super_block *) |
1005 | (bh->b_data + F2FS_SUPER_OFFSET); | 1015 | (bh->b_data + F2FS_SUPER_OFFSET); |
1016 | struct super_block *sb = sbi->sb; | ||
1006 | u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); | 1017 | u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); |
1007 | u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr); | 1018 | u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr); |
1008 | u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr); | 1019 | u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr); |
@@ -1081,6 +1092,7 @@ static inline bool sanity_check_area_boundary(struct super_block *sb, | |||
1081 | segment0_blkaddr) >> log_blocks_per_seg); | 1092 | segment0_blkaddr) >> log_blocks_per_seg); |
1082 | 1093 | ||
1083 | if (f2fs_readonly(sb) || bdev_read_only(sb->s_bdev)) { | 1094 | if (f2fs_readonly(sb) || bdev_read_only(sb->s_bdev)) { |
1095 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); | ||
1084 | res = "internally"; | 1096 | res = "internally"; |
1085 | } else { | 1097 | } else { |
1086 | err = __f2fs_commit_super(bh, NULL); | 1098 | err = __f2fs_commit_super(bh, NULL); |
@@ -1098,11 +1110,12 @@ static inline bool sanity_check_area_boundary(struct super_block *sb, | |||
1098 | return false; | 1110 | return false; |
1099 | } | 1111 | } |
1100 | 1112 | ||
1101 | static int sanity_check_raw_super(struct super_block *sb, | 1113 | static int sanity_check_raw_super(struct f2fs_sb_info *sbi, |
1102 | struct buffer_head *bh) | 1114 | struct buffer_head *bh) |
1103 | { | 1115 | { |
1104 | struct f2fs_super_block *raw_super = (struct f2fs_super_block *) | 1116 | struct f2fs_super_block *raw_super = (struct f2fs_super_block *) |
1105 | (bh->b_data + F2FS_SUPER_OFFSET); | 1117 | (bh->b_data + F2FS_SUPER_OFFSET); |
1118 | struct super_block *sb = sbi->sb; | ||
1106 | unsigned int blocksize; | 1119 | unsigned int blocksize; |
1107 | 1120 | ||
1108 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { | 1121 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { |
@@ -1169,7 +1182,7 @@ static int sanity_check_raw_super(struct super_block *sb, | |||
1169 | } | 1182 | } |
1170 | 1183 | ||
1171 | /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ | 1184 | /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ |
1172 | if (sanity_check_area_boundary(sb, bh)) | 1185 | if (sanity_check_area_boundary(sbi, bh)) |
1173 | return 1; | 1186 | return 1; |
1174 | 1187 | ||
1175 | return 0; | 1188 | return 0; |
@@ -1239,10 +1252,11 @@ static void init_sb_info(struct f2fs_sb_info *sbi) | |||
1239 | * to get the first valid one. If any one of them is broken, we pass | 1252 | * to get the first valid one. If any one of them is broken, we pass |
1240 | * them recovery flag back to the caller. | 1253 | * them recovery flag back to the caller. |
1241 | */ | 1254 | */ |
1242 | static int read_raw_super_block(struct super_block *sb, | 1255 | static int read_raw_super_block(struct f2fs_sb_info *sbi, |
1243 | struct f2fs_super_block **raw_super, | 1256 | struct f2fs_super_block **raw_super, |
1244 | int *valid_super_block, int *recovery) | 1257 | int *valid_super_block, int *recovery) |
1245 | { | 1258 | { |
1259 | struct super_block *sb = sbi->sb; | ||
1246 | int block; | 1260 | int block; |
1247 | struct buffer_head *bh; | 1261 | struct buffer_head *bh; |
1248 | struct f2fs_super_block *super; | 1262 | struct f2fs_super_block *super; |
@@ -1262,7 +1276,7 @@ static int read_raw_super_block(struct super_block *sb, | |||
1262 | } | 1276 | } |
1263 | 1277 | ||
1264 | /* sanity checking of raw super */ | 1278 | /* sanity checking of raw super */ |
1265 | if (sanity_check_raw_super(sb, bh)) { | 1279 | if (sanity_check_raw_super(sbi, bh)) { |
1266 | f2fs_msg(sb, KERN_ERR, | 1280 | f2fs_msg(sb, KERN_ERR, |
1267 | "Can't find valid F2FS filesystem in %dth superblock", | 1281 | "Can't find valid F2FS filesystem in %dth superblock", |
1268 | block + 1); | 1282 | block + 1); |
@@ -1298,8 +1312,11 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) | |||
1298 | struct buffer_head *bh; | 1312 | struct buffer_head *bh; |
1299 | int err; | 1313 | int err; |
1300 | 1314 | ||
1301 | if (f2fs_readonly(sbi->sb) || bdev_read_only(sbi->sb->s_bdev)) | 1315 | if ((recover && f2fs_readonly(sbi->sb)) || |
1316 | bdev_read_only(sbi->sb->s_bdev)) { | ||
1317 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); | ||
1302 | return -EROFS; | 1318 | return -EROFS; |
1319 | } | ||
1303 | 1320 | ||
1304 | /* write back-up superblock first */ | 1321 | /* write back-up superblock first */ |
1305 | bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0: 1); | 1322 | bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0: 1); |
@@ -1343,6 +1360,8 @@ try_onemore: | |||
1343 | if (!sbi) | 1360 | if (!sbi) |
1344 | return -ENOMEM; | 1361 | return -ENOMEM; |
1345 | 1362 | ||
1363 | sbi->sb = sb; | ||
1364 | |||
1346 | /* Load the checksum driver */ | 1365 | /* Load the checksum driver */ |
1347 | sbi->s_chksum_driver = crypto_alloc_shash("crc32", 0, 0); | 1366 | sbi->s_chksum_driver = crypto_alloc_shash("crc32", 0, 0); |
1348 | if (IS_ERR(sbi->s_chksum_driver)) { | 1367 | if (IS_ERR(sbi->s_chksum_driver)) { |
@@ -1358,7 +1377,7 @@ try_onemore: | |||
1358 | goto free_sbi; | 1377 | goto free_sbi; |
1359 | } | 1378 | } |
1360 | 1379 | ||
1361 | err = read_raw_super_block(sb, &raw_super, &valid_super_block, | 1380 | err = read_raw_super_block(sbi, &raw_super, &valid_super_block, |
1362 | &recovery); | 1381 | &recovery); |
1363 | if (err) | 1382 | if (err) |
1364 | goto free_sbi; | 1383 | goto free_sbi; |
@@ -1393,7 +1412,6 @@ try_onemore: | |||
1393 | memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid)); | 1412 | memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid)); |
1394 | 1413 | ||
1395 | /* init f2fs-specific super block info */ | 1414 | /* init f2fs-specific super block info */ |
1396 | sbi->sb = sb; | ||
1397 | sbi->raw_super = raw_super; | 1415 | sbi->raw_super = raw_super; |
1398 | sbi->valid_super_block = valid_super_block; | 1416 | sbi->valid_super_block = valid_super_block; |
1399 | mutex_init(&sbi->gc_mutex); | 1417 | mutex_init(&sbi->gc_mutex); |