f2fs: return error during fill_super
Let's avoid BUG_ON during fill_super, when on-disk was totall corrupted. Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
211a6fa04c
commit
c39a1b348c
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
/*
|
/*
|
||||||
* 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,
|
||||||
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,
|
||||||
|
|
Loading…
Reference in New Issue