diff options
-rw-r--r-- | fs/f2fs/checkpoint.c | 36 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 3 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 8 | ||||
-rw-r--r-- | fs/f2fs/super.c | 12 |
4 files changed, 31 insertions, 28 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index ff3c8439af87..9c1627165039 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -72,22 +72,22 @@ static int f2fs_write_meta_page(struct page *page, | |||
72 | { | 72 | { |
73 | struct inode *inode = page->mapping->host; | 73 | struct inode *inode = page->mapping->host; |
74 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 74 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
75 | int err; | ||
76 | 75 | ||
77 | wait_on_page_writeback(page); | 76 | /* Should not write any meta pages, if any IO error was occurred */ |
78 | 77 | if (wbc->for_reclaim || | |
79 | err = write_meta_page(sbi, page, wbc); | 78 | is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) { |
80 | if (err) { | 79 | dec_page_count(sbi, F2FS_DIRTY_META); |
81 | wbc->pages_skipped++; | 80 | wbc->pages_skipped++; |
82 | set_page_dirty(page); | 81 | set_page_dirty(page); |
82 | return AOP_WRITEPAGE_ACTIVATE; | ||
83 | } | 83 | } |
84 | 84 | ||
85 | dec_page_count(sbi, F2FS_DIRTY_META); | 85 | wait_on_page_writeback(page); |
86 | 86 | ||
87 | /* In this case, we should not unlock this page */ | 87 | write_meta_page(sbi, page); |
88 | if (err != AOP_WRITEPAGE_ACTIVATE) | 88 | dec_page_count(sbi, F2FS_DIRTY_META); |
89 | unlock_page(page); | 89 | unlock_page(page); |
90 | return err; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int f2fs_write_meta_pages(struct address_space *mapping, | 93 | static int f2fs_write_meta_pages(struct address_space *mapping, |
@@ -138,7 +138,10 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, | |||
138 | BUG_ON(page->mapping != mapping); | 138 | BUG_ON(page->mapping != mapping); |
139 | BUG_ON(!PageDirty(page)); | 139 | BUG_ON(!PageDirty(page)); |
140 | clear_page_dirty_for_io(page); | 140 | clear_page_dirty_for_io(page); |
141 | f2fs_write_meta_page(page, &wbc); | 141 | if (f2fs_write_meta_page(page, &wbc)) { |
142 | unlock_page(page); | ||
143 | break; | ||
144 | } | ||
142 | if (nwritten++ >= nr_to_write) | 145 | if (nwritten++ >= nr_to_write) |
143 | break; | 146 | break; |
144 | } | 147 | } |
@@ -717,13 +720,12 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
717 | sbi->alloc_valid_block_count = 0; | 720 | sbi->alloc_valid_block_count = 0; |
718 | 721 | ||
719 | /* Here, we only have one bio having CP pack */ | 722 | /* Here, we only have one bio having CP pack */ |
720 | if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) | 723 | sync_meta_pages(sbi, META_FLUSH, LONG_MAX); |
721 | sbi->sb->s_flags |= MS_RDONLY; | ||
722 | else | ||
723 | sync_meta_pages(sbi, META_FLUSH, LONG_MAX); | ||
724 | 724 | ||
725 | clear_prefree_segments(sbi); | 725 | if (!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) { |
726 | F2FS_RESET_SB_DIRT(sbi); | 726 | clear_prefree_segments(sbi); |
727 | F2FS_RESET_SB_DIRT(sbi); | ||
728 | } | ||
727 | } | 729 | } |
728 | 730 | ||
729 | /* | 731 | /* |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index c8e2d751ef9c..f4f509766465 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -929,8 +929,7 @@ void allocate_new_segments(struct f2fs_sb_info *); | |||
929 | struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); | 929 | struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); |
930 | struct bio *f2fs_bio_alloc(struct block_device *, int); | 930 | struct bio *f2fs_bio_alloc(struct block_device *, int); |
931 | void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync); | 931 | void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync); |
932 | int write_meta_page(struct f2fs_sb_info *, struct page *, | 932 | void write_meta_page(struct f2fs_sb_info *, struct page *); |
933 | struct writeback_control *); | ||
934 | void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, | 933 | void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int, |
935 | block_t, block_t *); | 934 | block_t, block_t *); |
936 | void write_data_page(struct inode *, struct page *, struct dnode_of_data*, | 935 | void write_data_page(struct inode *, struct page *, struct dnode_of_data*, |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 4b0099066582..7aa270f3538a 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -600,6 +600,7 @@ static void f2fs_end_io_write(struct bio *bio, int err) | |||
600 | if (page->mapping) | 600 | if (page->mapping) |
601 | set_bit(AS_EIO, &page->mapping->flags); | 601 | set_bit(AS_EIO, &page->mapping->flags); |
602 | set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG); | 602 | set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG); |
603 | p->sbi->sb->s_flags |= MS_RDONLY; | ||
603 | } | 604 | } |
604 | end_page_writeback(page); | 605 | end_page_writeback(page); |
605 | dec_page_count(p->sbi, F2FS_WRITEBACK); | 606 | dec_page_count(p->sbi, F2FS_WRITEBACK); |
@@ -815,15 +816,10 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, | |||
815 | mutex_unlock(&curseg->curseg_mutex); | 816 | mutex_unlock(&curseg->curseg_mutex); |
816 | } | 817 | } |
817 | 818 | ||
818 | int write_meta_page(struct f2fs_sb_info *sbi, struct page *page, | 819 | void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) |
819 | struct writeback_control *wbc) | ||
820 | { | 820 | { |
821 | if (wbc->for_reclaim) | ||
822 | return AOP_WRITEPAGE_ACTIVATE; | ||
823 | |||
824 | set_page_writeback(page); | 821 | set_page_writeback(page); |
825 | submit_write_page(sbi, page, page->index, META); | 822 | submit_write_page(sbi, page, page->index, META); |
826 | return 0; | ||
827 | } | 823 | } |
828 | 824 | ||
829 | void write_node_page(struct f2fs_sb_info *sbi, struct page *page, | 825 | void write_node_page(struct f2fs_sb_info *sbi, struct page *page, |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 37fad04c8669..117ca2a46e39 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -387,10 +387,11 @@ static int sanity_check_raw_super(struct super_block *sb, | |||
387 | return 0; | 387 | return 0; |
388 | } | 388 | } |
389 | 389 | ||
390 | static int sanity_check_ckpt(struct f2fs_super_block *raw_super, | 390 | static int sanity_check_ckpt(struct f2fs_sb_info *sbi) |
391 | struct f2fs_checkpoint *ckpt) | ||
392 | { | 391 | { |
393 | unsigned int total, fsmeta; | 392 | unsigned int total, fsmeta; |
393 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | ||
394 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | ||
394 | 395 | ||
395 | total = le32_to_cpu(raw_super->segment_count); | 396 | total = le32_to_cpu(raw_super->segment_count); |
396 | fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); | 397 | fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); |
@@ -401,6 +402,11 @@ static int sanity_check_ckpt(struct f2fs_super_block *raw_super, | |||
401 | 402 | ||
402 | if (fsmeta >= total) | 403 | if (fsmeta >= total) |
403 | return 1; | 404 | return 1; |
405 | |||
406 | if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) { | ||
407 | f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck"); | ||
408 | return 1; | ||
409 | } | ||
404 | return 0; | 410 | return 0; |
405 | } | 411 | } |
406 | 412 | ||
@@ -525,7 +531,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
525 | 531 | ||
526 | /* sanity checking of checkpoint */ | 532 | /* sanity checking of checkpoint */ |
527 | err = -EINVAL; | 533 | err = -EINVAL; |
528 | if (sanity_check_ckpt(raw_super, sbi->ckpt)) { | 534 | if (sanity_check_ckpt(sbi)) { |
529 | f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint"); | 535 | f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint"); |
530 | goto free_cp; | 536 | goto free_cp; |
531 | } | 537 | } |