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); |
