Commit c39a1b34 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: return error during fill_super

Let's avoid BUG_ON during fill_super, when on-disk was totall corrupted.
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 211a6fa0
...@@ -3476,7 +3476,7 @@ static int build_curseg(struct f2fs_sb_info *sbi) ...@@ -3476,7 +3476,7 @@ static int build_curseg(struct f2fs_sb_info *sbi)
return restore_curseg_summaries(sbi); return restore_curseg_summaries(sbi);
} }
static void build_sit_entries(struct f2fs_sb_info *sbi) static int build_sit_entries(struct f2fs_sb_info *sbi)
{ {
struct sit_info *sit_i = SIT_I(sbi); struct sit_info *sit_i = SIT_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
...@@ -3486,6 +3486,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) ...@@ -3486,6 +3486,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
int sit_blk_cnt = SIT_BLK_CNT(sbi); int sit_blk_cnt = SIT_BLK_CNT(sbi);
unsigned int i, start, end; unsigned int i, start, end;
unsigned int readed, start_blk = 0; unsigned int readed, start_blk = 0;
int err = 0;
do { do {
readed = ra_meta_pages(sbi, start_blk, BIO_MAX_PAGES, readed = ra_meta_pages(sbi, start_blk, BIO_MAX_PAGES,
...@@ -3504,7 +3505,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) ...@@ -3504,7 +3505,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
f2fs_put_page(page, 1); f2fs_put_page(page, 1);
check_block_count(sbi, start, &sit); err = check_block_count(sbi, start, &sit);
if (err)
return err;
seg_info_from_raw_sit(se, &sit); seg_info_from_raw_sit(se, &sit);
/* build discard map only one time */ /* build discard map only one time */
...@@ -3539,7 +3542,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) ...@@ -3539,7 +3542,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
old_valid_blocks = se->valid_blocks; old_valid_blocks = se->valid_blocks;
check_block_count(sbi, start, &sit); err = check_block_count(sbi, start, &sit);
if (err)
break;
seg_info_from_raw_sit(se, &sit); seg_info_from_raw_sit(se, &sit);
if (f2fs_discard_en(sbi)) { if (f2fs_discard_en(sbi)) {
...@@ -3559,6 +3564,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) ...@@ -3559,6 +3564,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
se->valid_blocks - old_valid_blocks; se->valid_blocks - old_valid_blocks;
} }
up_read(&curseg->journal_rwsem); up_read(&curseg->journal_rwsem);
return err;
} }
static void init_free_segmap(struct f2fs_sb_info *sbi) static void init_free_segmap(struct f2fs_sb_info *sbi)
...@@ -3733,7 +3739,9 @@ int build_segment_manager(struct f2fs_sb_info *sbi) ...@@ -3733,7 +3739,9 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
return err; return err;
/* reinit free segmap based on SIT */ /* reinit free segmap based on SIT */
build_sit_entries(sbi); err = build_sit_entries(sbi);
if (err)
return err;
init_free_segmap(sbi); init_free_segmap(sbi);
err = build_dirty_segmap(sbi); err = build_dirty_segmap(sbi);
......
...@@ -655,7 +655,7 @@ static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) ...@@ -655,7 +655,7 @@ static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
/* /*
* Summary block is always treated as an invalid block * Summary block is always treated as an invalid block
*/ */
static inline void check_block_count(struct f2fs_sb_info *sbi, static inline int check_block_count(struct f2fs_sb_info *sbi,
int segno, struct f2fs_sit_entry *raw_sit) int segno, struct f2fs_sit_entry *raw_sit)
{ {
#ifdef CONFIG_F2FS_CHECK_FS #ifdef CONFIG_F2FS_CHECK_FS
...@@ -677,11 +677,25 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, ...@@ -677,11 +677,25 @@ static inline void check_block_count(struct f2fs_sb_info *sbi,
cur_pos = next_pos; cur_pos = next_pos;
is_valid = !is_valid; is_valid = !is_valid;
} while (cur_pos < sbi->blocks_per_seg); } while (cur_pos < sbi->blocks_per_seg);
BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
if (unlikely(GET_SIT_VBLOCKS(raw_sit) != valid_blocks)) {
f2fs_msg(sbi->sb, KERN_ERR,
"Mismatch valid blocks %d vs. %d",
GET_SIT_VBLOCKS(raw_sit), valid_blocks);
set_sbi_flag(sbi, SBI_NEED_FSCK);
return -EINVAL;
}
#endif #endif
/* check segment usage, and check boundary of a given segment number */ /* check segment usage, and check boundary of a given segment number */
f2fs_bug_on(sbi, GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg
|| segno > TOTAL_SEGS(sbi) - 1); || segno > TOTAL_SEGS(sbi) - 1)) {
f2fs_msg(sbi->sb, KERN_ERR,
"Wrong valid blocks %d or segno %u",
GET_SIT_VBLOCKS(raw_sit), segno);
set_sbi_flag(sbi, SBI_NEED_FSCK);
return -EINVAL;
}
return 0;
} }
static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment