|
@@ -160,14 +160,11 @@ static int f2fs_write_meta_page(struct page *page,
|
|
goto redirty_out;
|
|
goto redirty_out;
|
|
if (wbc->for_reclaim)
|
|
if (wbc->for_reclaim)
|
|
goto redirty_out;
|
|
goto redirty_out;
|
|
-
|
|
|
|
- /* Should not write any meta pages, if any IO error was occurred */
|
|
|
|
if (unlikely(f2fs_cp_error(sbi)))
|
|
if (unlikely(f2fs_cp_error(sbi)))
|
|
- goto no_write;
|
|
|
|
|
|
+ goto redirty_out;
|
|
|
|
|
|
f2fs_wait_on_page_writeback(page, META);
|
|
f2fs_wait_on_page_writeback(page, META);
|
|
write_meta_page(sbi, page);
|
|
write_meta_page(sbi, page);
|
|
-no_write:
|
|
|
|
dec_page_count(sbi, F2FS_DIRTY_META);
|
|
dec_page_count(sbi, F2FS_DIRTY_META);
|
|
unlock_page(page);
|
|
unlock_page(page);
|
|
return 0;
|
|
return 0;
|
|
@@ -737,7 +734,7 @@ retry:
|
|
/*
|
|
/*
|
|
* Freeze all the FS-operations for checkpoint.
|
|
* Freeze all the FS-operations for checkpoint.
|
|
*/
|
|
*/
|
|
-static void block_operations(struct f2fs_sb_info *sbi)
|
|
|
|
|
|
+static int block_operations(struct f2fs_sb_info *sbi)
|
|
{
|
|
{
|
|
struct writeback_control wbc = {
|
|
struct writeback_control wbc = {
|
|
.sync_mode = WB_SYNC_ALL,
|
|
.sync_mode = WB_SYNC_ALL,
|
|
@@ -745,6 +742,7 @@ static void block_operations(struct f2fs_sb_info *sbi)
|
|
.for_reclaim = 0,
|
|
.for_reclaim = 0,
|
|
};
|
|
};
|
|
struct blk_plug plug;
|
|
struct blk_plug plug;
|
|
|
|
+ int err = 0;
|
|
|
|
|
|
blk_start_plug(&plug);
|
|
blk_start_plug(&plug);
|
|
|
|
|
|
@@ -754,6 +752,10 @@ retry_flush_dents:
|
|
if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
|
|
if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
|
|
f2fs_unlock_all(sbi);
|
|
f2fs_unlock_all(sbi);
|
|
sync_dirty_dir_inodes(sbi);
|
|
sync_dirty_dir_inodes(sbi);
|
|
|
|
+ if (unlikely(f2fs_cp_error(sbi))) {
|
|
|
|
+ err = -EIO;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
goto retry_flush_dents;
|
|
goto retry_flush_dents;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -767,9 +769,16 @@ retry_flush_nodes:
|
|
if (get_pages(sbi, F2FS_DIRTY_NODES)) {
|
|
if (get_pages(sbi, F2FS_DIRTY_NODES)) {
|
|
up_write(&sbi->node_write);
|
|
up_write(&sbi->node_write);
|
|
sync_node_pages(sbi, 0, &wbc);
|
|
sync_node_pages(sbi, 0, &wbc);
|
|
|
|
+ if (unlikely(f2fs_cp_error(sbi))) {
|
|
|
|
+ f2fs_unlock_all(sbi);
|
|
|
|
+ err = -EIO;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
goto retry_flush_nodes;
|
|
goto retry_flush_nodes;
|
|
}
|
|
}
|
|
|
|
+out:
|
|
blk_finish_plug(&plug);
|
|
blk_finish_plug(&plug);
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
|
|
|
|
static void unblock_operations(struct f2fs_sb_info *sbi)
|
|
static void unblock_operations(struct f2fs_sb_info *sbi)
|
|
@@ -813,8 +822,11 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
|
|
discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg));
|
|
discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg));
|
|
|
|
|
|
/* Flush all the NAT/SIT pages */
|
|
/* Flush all the NAT/SIT pages */
|
|
- while (get_pages(sbi, F2FS_DIRTY_META))
|
|
|
|
|
|
+ while (get_pages(sbi, F2FS_DIRTY_META)) {
|
|
sync_meta_pages(sbi, META, LONG_MAX);
|
|
sync_meta_pages(sbi, META, LONG_MAX);
|
|
|
|
+ if (unlikely(f2fs_cp_error(sbi)))
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
next_free_nid(sbi, &last_nid);
|
|
next_free_nid(sbi, &last_nid);
|
|
|
|
|
|
@@ -924,6 +936,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
|
|
/* wait for previous submitted node/meta pages writeback */
|
|
/* wait for previous submitted node/meta pages writeback */
|
|
wait_on_all_pages_writeback(sbi);
|
|
wait_on_all_pages_writeback(sbi);
|
|
|
|
|
|
|
|
+ if (unlikely(f2fs_cp_error(sbi)))
|
|
|
|
+ return;
|
|
|
|
+
|
|
filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX);
|
|
filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX);
|
|
filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX);
|
|
filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX);
|
|
|
|
|
|
@@ -934,11 +949,13 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
|
|
/* Here, we only have one bio having CP pack */
|
|
/* Here, we only have one bio having CP pack */
|
|
sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
|
|
sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
|
|
|
|
|
|
- if (!f2fs_cp_error(sbi)) {
|
|
|
|
- clear_prefree_segments(sbi);
|
|
|
|
- release_dirty_inode(sbi);
|
|
|
|
- F2FS_RESET_SB_DIRT(sbi);
|
|
|
|
- }
|
|
|
|
|
|
+ release_dirty_inode(sbi);
|
|
|
|
+
|
|
|
|
+ if (unlikely(f2fs_cp_error(sbi)))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ clear_prefree_segments(sbi);
|
|
|
|
+ F2FS_RESET_SB_DIRT(sbi);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -955,8 +972,10 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
|
|
|
|
|
|
if (!sbi->s_dirty)
|
|
if (!sbi->s_dirty)
|
|
goto out;
|
|
goto out;
|
|
-
|
|
|
|
- block_operations(sbi);
|
|
|
|
|
|
+ if (unlikely(f2fs_cp_error(sbi)))
|
|
|
|
+ goto out;
|
|
|
|
+ if (block_operations(sbi))
|
|
|
|
+ goto out;
|
|
|
|
|
|
trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");
|
|
trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");
|
|
|
|
|