aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-08-11 21:37:46 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2014-08-21 16:55:05 -0400
commitcf779cab14d50a84b61399f758da269654b863db (patch)
treec11a1da5ea17f3e3f86e5cdad7cc57b97427e7fa /fs/f2fs
parent8501017e50fb7586ba522a2913ce664d6c2024f6 (diff)
f2fs: handle EIO not to break fs consistency
There are two rules when EIO is occurred. 1. don't write any checkpoint data to preserve the previous checkpoint 2. don't lose the cached dentry/node/meta pages So, at first, this patch adds set_page_dirty in f2fs_write_end_io's failure. Then, writing checkpoint/dentry/node blocks is not allowed. Note that, for the data pages, we can't just throw away by redirtying them. Otherwise, kworker can fall into infinite loop to flush them. (Ref. xfstests/019) Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/checkpoint.c45
-rw-r--r--fs/f2fs/data.c11
-rw-r--r--fs/f2fs/node.c2
-rw-r--r--fs/f2fs/super.c5
4 files changed, 48 insertions, 15 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index dc29b7837687..c9c08d52ecfd 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -160,14 +160,11 @@ static int f2fs_write_meta_page(struct page *page,
160 goto redirty_out; 160 goto redirty_out;
161 if (wbc->for_reclaim) 161 if (wbc->for_reclaim)
162 goto redirty_out; 162 goto redirty_out;
163
164 /* Should not write any meta pages, if any IO error was occurred */
165 if (unlikely(f2fs_cp_error(sbi))) 163 if (unlikely(f2fs_cp_error(sbi)))
166 goto no_write; 164 goto redirty_out;
167 165
168 f2fs_wait_on_page_writeback(page, META); 166 f2fs_wait_on_page_writeback(page, META);
169 write_meta_page(sbi, page); 167 write_meta_page(sbi, page);
170no_write:
171 dec_page_count(sbi, F2FS_DIRTY_META); 168 dec_page_count(sbi, F2FS_DIRTY_META);
172 unlock_page(page); 169 unlock_page(page);
173 return 0; 170 return 0;
@@ -737,7 +734,7 @@ retry:
737/* 734/*
738 * Freeze all the FS-operations for checkpoint. 735 * Freeze all the FS-operations for checkpoint.
739 */ 736 */
740static void block_operations(struct f2fs_sb_info *sbi) 737static int block_operations(struct f2fs_sb_info *sbi)
741{ 738{
742 struct writeback_control wbc = { 739 struct writeback_control wbc = {
743 .sync_mode = WB_SYNC_ALL, 740 .sync_mode = WB_SYNC_ALL,
@@ -745,6 +742,7 @@ static void block_operations(struct f2fs_sb_info *sbi)
745 .for_reclaim = 0, 742 .for_reclaim = 0,
746 }; 743 };
747 struct blk_plug plug; 744 struct blk_plug plug;
745 int err = 0;
748 746
749 blk_start_plug(&plug); 747 blk_start_plug(&plug);
750 748
@@ -754,6 +752,10 @@ retry_flush_dents:
754 if (get_pages(sbi, F2FS_DIRTY_DENTS)) { 752 if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
755 f2fs_unlock_all(sbi); 753 f2fs_unlock_all(sbi);
756 sync_dirty_dir_inodes(sbi); 754 sync_dirty_dir_inodes(sbi);
755 if (unlikely(f2fs_cp_error(sbi))) {
756 err = -EIO;
757 goto out;
758 }
757 goto retry_flush_dents; 759 goto retry_flush_dents;
758 } 760 }
759 761
@@ -767,9 +769,16 @@ retry_flush_nodes:
767 if (get_pages(sbi, F2FS_DIRTY_NODES)) { 769 if (get_pages(sbi, F2FS_DIRTY_NODES)) {
768 up_write(&sbi->node_write); 770 up_write(&sbi->node_write);
769 sync_node_pages(sbi, 0, &wbc); 771 sync_node_pages(sbi, 0, &wbc);
772 if (unlikely(f2fs_cp_error(sbi))) {
773 f2fs_unlock_all(sbi);
774 err = -EIO;
775 goto out;
776 }
770 goto retry_flush_nodes; 777 goto retry_flush_nodes;
771 } 778 }
779out:
772 blk_finish_plug(&plug); 780 blk_finish_plug(&plug);
781 return err;
773} 782}
774 783
775static void unblock_operations(struct f2fs_sb_info *sbi) 784static void unblock_operations(struct f2fs_sb_info *sbi)
@@ -813,8 +822,11 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
813 discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg)); 822 discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg));
814 823
815 /* Flush all the NAT/SIT pages */ 824 /* Flush all the NAT/SIT pages */
816 while (get_pages(sbi, F2FS_DIRTY_META)) 825 while (get_pages(sbi, F2FS_DIRTY_META)) {
817 sync_meta_pages(sbi, META, LONG_MAX); 826 sync_meta_pages(sbi, META, LONG_MAX);
827 if (unlikely(f2fs_cp_error(sbi)))
828 return;
829 }
818 830
819 next_free_nid(sbi, &last_nid); 831 next_free_nid(sbi, &last_nid);
820 832
@@ -924,6 +936,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
924 /* wait for previous submitted node/meta pages writeback */ 936 /* wait for previous submitted node/meta pages writeback */
925 wait_on_all_pages_writeback(sbi); 937 wait_on_all_pages_writeback(sbi);
926 938
939 if (unlikely(f2fs_cp_error(sbi)))
940 return;
941
927 filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX); 942 filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX);
928 filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX); 943 filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX);
929 944
@@ -934,11 +949,13 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
934 /* Here, we only have one bio having CP pack */ 949 /* Here, we only have one bio having CP pack */
935 sync_meta_pages(sbi, META_FLUSH, LONG_MAX); 950 sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
936 951
937 if (!f2fs_cp_error(sbi)) { 952 release_dirty_inode(sbi);
938 clear_prefree_segments(sbi); 953
939 release_dirty_inode(sbi); 954 if (unlikely(f2fs_cp_error(sbi)))
940 F2FS_RESET_SB_DIRT(sbi); 955 return;
941 } 956
957 clear_prefree_segments(sbi);
958 F2FS_RESET_SB_DIRT(sbi);
942} 959}
943 960
944/* 961/*
@@ -955,8 +972,10 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
955 972
956 if (!sbi->s_dirty) 973 if (!sbi->s_dirty)
957 goto out; 974 goto out;
958 975 if (unlikely(f2fs_cp_error(sbi)))
959 block_operations(sbi); 976 goto out;
977 if (block_operations(sbi))
978 goto out;
960 979
961 trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops"); 980 trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");
962 981
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index ac3ccc25386b..6ba52a393063 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -53,7 +53,7 @@ static void f2fs_write_end_io(struct bio *bio, int err)
53 struct page *page = bvec->bv_page; 53 struct page *page = bvec->bv_page;
54 54
55 if (unlikely(err)) { 55 if (unlikely(err)) {
56 SetPageError(page); 56 set_page_dirty(page);
57 set_bit(AS_EIO, &page->mapping->flags); 57 set_bit(AS_EIO, &page->mapping->flags);
58 f2fs_stop_checkpoint(sbi); 58 f2fs_stop_checkpoint(sbi);
59 } 59 }
@@ -836,10 +836,19 @@ write:
836 836
837 /* Dentry blocks are controlled by checkpoint */ 837 /* Dentry blocks are controlled by checkpoint */
838 if (S_ISDIR(inode->i_mode)) { 838 if (S_ISDIR(inode->i_mode)) {
839 if (unlikely(f2fs_cp_error(sbi)))
840 goto redirty_out;
839 err = do_write_data_page(page, &fio); 841 err = do_write_data_page(page, &fio);
840 goto done; 842 goto done;
841 } 843 }
842 844
845 /* we should bypass data pages to proceed the kworkder jobs */
846 if (unlikely(f2fs_cp_error(sbi))) {
847 SetPageError(page);
848 unlock_page(page);
849 return 0;
850 }
851
843 if (!wbc->for_reclaim) 852 if (!wbc->for_reclaim)
844 need_balance_fs = true; 853 need_balance_fs = true;
845 else if (has_not_enough_free_secs(sbi, 0)) 854 else if (has_not_enough_free_secs(sbi, 0))
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 9f126f80813d..d2f784283425 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1215,6 +1215,8 @@ static int f2fs_write_node_page(struct page *page,
1215 1215
1216 if (unlikely(sbi->por_doing)) 1216 if (unlikely(sbi->por_doing))
1217 goto redirty_out; 1217 goto redirty_out;
1218 if (unlikely(f2fs_cp_error(sbi)))
1219 goto redirty_out;
1218 1220
1219 f2fs_wait_on_page_writeback(page, NODE); 1221 f2fs_wait_on_page_writeback(page, NODE);
1220 1222
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index e7a7b619ffd4..ddb1e9d36363 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -435,7 +435,10 @@ static void f2fs_put_super(struct super_block *sb)
435 if (sbi->s_dirty) 435 if (sbi->s_dirty)
436 write_checkpoint(sbi, true); 436 write_checkpoint(sbi, true);
437 437
438 /* normally superblock is clean, so we need to release this */ 438 /*
439 * normally superblock is clean, so we need to release this.
440 * In addition, EIO will skip do checkpoint, we need this as well.
441 */
439 release_dirty_inode(sbi); 442 release_dirty_inode(sbi);
440 443
441 iput(sbi->node_inode); 444 iput(sbi->node_inode);