Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5943e399 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

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 93579c97
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -3476,7 +3476,7 @@ static int build_curseg(struct f2fs_sb_info *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 curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
@@ -3486,6 +3486,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
	int sit_blk_cnt = SIT_BLK_CNT(sbi);
	unsigned int i, start, end;
	unsigned int readed, start_blk = 0;
	int err = 0;

	do {
		readed = ra_meta_pages(sbi, start_blk, BIO_MAX_PAGES,
@@ -3504,7 +3505,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
			sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
			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);

			/* build discard map only one time */
@@ -3539,7 +3542,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)

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

		if (f2fs_discard_en(sbi)) {
@@ -3559,6 +3564,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
				se->valid_blocks - old_valid_blocks;
	}
	up_read(&curseg->journal_rwsem);
	return err;
}

static void init_free_segmap(struct f2fs_sb_info *sbi)
@@ -3733,7 +3739,9 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
		return err;

	/* reinit free segmap based on SIT */
	build_sit_entries(sbi);
	err = build_sit_entries(sbi);
	if (err)
		return err;

	init_free_segmap(sbi);
	err = build_dirty_segmap(sbi);
+18 −4
Original line number Diff line number Diff line
@@ -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
 */
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)
{
#ifdef CONFIG_F2FS_CHECK_FS
@@ -677,11 +677,25 @@ static inline void check_block_count(struct f2fs_sb_info *sbi,
		cur_pos = next_pos;
		is_valid = !is_valid;
	} 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
	/* check segment usage, and check boundary of a given segment number */
	f2fs_bug_on(sbi, GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg
					|| segno > TOTAL_SEGS(sbi) - 1);
	if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg
					|| 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,