diff options
-rw-r--r-- | fs/f2fs/checkpoint.c | 45 | ||||
-rw-r--r-- | fs/f2fs/data.c | 11 | ||||
-rw-r--r-- | fs/f2fs/node.c | 2 | ||||
-rw-r--r-- | fs/f2fs/super.c | 5 |
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); |
170 | no_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 | */ |
740 | static void block_operations(struct f2fs_sb_info *sbi) | 737 | static 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 | } |
779 | out: | ||
772 | blk_finish_plug(&plug); | 780 | blk_finish_plug(&plug); |
781 | return err; | ||
773 | } | 782 | } |
774 | 783 | ||
775 | static void unblock_operations(struct f2fs_sb_info *sbi) | 784 | 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) | |||
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); |