f2fs: fix to stop filesystem update once CP failed
During f2fs_write_checkpoint(), once we failed in f2fs_flush_nat_entries() or do_checkpoint(), metadata of filesystem such as prefree bitmap, nat/sit version bitmap won't be recovered, it may cause f2fs image to be inconsistent, let's just set CP error flag to avoid further updates until we figure out a scheme to rollback all metadatas in such condition. Reported-by: Yangtao Li <frank.li@vivo.com> Signed-off-by: Yangtao Li <frank.li@vivo.com> Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Родитель
0f6b56ec95
Коммит
91803392c7
|
@ -1639,8 +1639,11 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
|||
|
||||
/* write cached NAT/SIT entries to NAT/SIT area */
|
||||
err = f2fs_flush_nat_entries(sbi, cpc);
|
||||
if (err)
|
||||
if (err) {
|
||||
f2fs_err(sbi, "f2fs_flush_nat_entries failed err:%d, stop checkpoint", err);
|
||||
f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
|
||||
goto stop;
|
||||
}
|
||||
|
||||
f2fs_flush_sit_entries(sbi, cpc);
|
||||
|
||||
|
@ -1648,10 +1651,13 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
|||
f2fs_save_inmem_curseg(sbi);
|
||||
|
||||
err = do_checkpoint(sbi, cpc);
|
||||
if (err)
|
||||
if (err) {
|
||||
f2fs_err(sbi, "do_checkpoint failed err:%d, stop checkpoint", err);
|
||||
f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
|
||||
f2fs_release_discard_addrs(sbi);
|
||||
else
|
||||
} else {
|
||||
f2fs_clear_prefree_segments(sbi, cpc);
|
||||
}
|
||||
|
||||
f2fs_restore_inmem_curseg(sbi);
|
||||
stop:
|
||||
|
|
|
@ -547,7 +547,7 @@ enum {
|
|||
*/
|
||||
};
|
||||
|
||||
#define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO count */
|
||||
#define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO or flush count */
|
||||
|
||||
/* congestion wait timeout value, default: 20ms */
|
||||
#define DEFAULT_IO_TIMEOUT (msecs_to_jiffies(20))
|
||||
|
|
|
@ -776,11 +776,22 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
|
|||
return 0;
|
||||
|
||||
for (i = 1; i < sbi->s_ndevs; i++) {
|
||||
int count = DEFAULT_RETRY_IO_COUNT;
|
||||
|
||||
if (!f2fs_test_bit(i, (char *)&sbi->dirty_device))
|
||||
continue;
|
||||
ret = __submit_flush_wait(sbi, FDEV(i).bdev);
|
||||
if (ret)
|
||||
|
||||
do {
|
||||
ret = __submit_flush_wait(sbi, FDEV(i).bdev);
|
||||
if (ret)
|
||||
congestion_wait(BLK_RW_ASYNC,
|
||||
DEFAULT_IO_TIMEOUT);
|
||||
} while (ret && --count);
|
||||
|
||||
if (ret) {
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock(&sbi->dev_lock);
|
||||
f2fs_clear_bit(i, (char *)&sbi->dirty_device);
|
||||
|
|
Загрузка…
Ссылка в новой задаче