Hi Ju Hyung, On 2019/5/15 12:50, Ju Hyung Park wrote: > Hi Chao, > > The new logs are at > http://arter97.com/f2fs/v3 > > The first run spits out 60MB worth of log > and the second run spits out 170MB worth of log > and the third run now returns everything's ok. > > Returning ok after 2nd run is good news, but the user would expect > everything to be fixed with just the first run of fsck'ing. Is this > expected?
No, I think we should fix all problem at first time. I checked the log and code, and have no idea why this happened, the logs show that valid block still has invalid sit bitmap after 1st fsck. log1, line: 381518 [ASSERT] (fsck_chk_data_blk:1640) --> SIT bitmap is 0x0. blk_addr[0x36ea64c] log2, line: 128537 [ASSERT] (fsck_chk_data_blk:1640) --> SIT bitmap is 0x0. blk_addr[0x36ea64c] However, it shouldn't be, since we will repair sit bitmap in below path: - fsck_verify - rewrite_sit_area_bitmap So I doubt that sit version bitmap is corrupted, could you add below log and reproduce this issue? diff --git a/fsck/fsck.c b/fsck/fsck.c index b5daeb4..0fc9919 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -1617,6 +1617,9 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, int enc_name) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + struct sit_info *sit_i = SIT_I(sbi); + unsigned int offset = + SIT_BLOCK_OFFSET(sit_i, GET_SEGNO(sbi, blk_addr)); /* Is it reserved block? */ if (blk_addr == NEW_ADDR) { @@ -1637,7 +1640,9 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, } if (f2fs_test_sit_bitmap(sbi, blk_addr) == 0) - ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", blk_addr); + ASSERT_MSG("SIT bitmap is 0x0. bitmap:%d, blk_addr[0x%x]", + f2fs_test_bit(offset, sit_i->sit_bitmap) + blk_addr); if (f2fs_test_main_bitmap(sbi, blk_addr) != 0) ASSERT_MSG("Duplicated data [0x%x]. pnid[0x%x] idx[0x%x]", Thanks, > > I'll test the new kernel soon. > > Thanks. > > On Tue, May 14, 2019 at 6:54 PM Ju Hyung Park <qkrwngud...@gmail.com> wrote: >> >> Ah, sorry. I typed too soon. >> >> I'll make sure to test this sooner than later. >> Sorry for the delay. >> >> Thanks :) >> >> On Tue, May 14, 2019, 6:43 PM Chao Yu <yuch...@huawei.com> wrote: >>> >>> Hi Ju Hyung, >>> >>> This is the change on tools part. ;) >>> >>> Thanks, >>> >>> On 2019/5/14 17:38, Ju Hyung Park wrote: >>>> Hi Chao, >>>> >>>> I believe Jaegeuk already queued v2 for Linus, I think you should probably >>>> make this as a separate patch. >>>> >>>> Thanks. >>>> >>>> On Tue, May 14, 2019, 6:35 PM Chao Yu <yuch...@huawei.com> wrote: >>>> >>>>> For large_nat_bitmap feature, there is a design flaw: >>>>> >>>>> Previous: >>>>> >>>>> struct f2fs_checkpoint layout: >>>>> +--------------------------+ 0x0000 >>>>> | checkpoint_ver | >>>>> | ...... | >>>>> | checksum_offset |------+ >>>>> | ...... | | >>>>> | sit_nat_version_bitmap[] |<-----|-------+ >>>>> | ...... | | | >>>>> | checksum_value |<-----+ | >>>>> +--------------------------+ 0x1000 | >>>>> | | nat_bitmap + sit_bitmap >>>>> | payload blocks | | >>>>> | | | >>>>> +--------------------------|<-------------+ >>>>> >>>>> Obviously, if nat_bitmap size + sit_bitmap size is larger than >>>>> MAX_BITMAP_SIZE_IN_CKPT, nat_bitmap or sit_bitmap may overlap >>>>> checkpoint checksum's position, once checkpoint() is triggered >>>>> from kernel, nat or sit bitmap will be damaged by checksum field. >>>>> >>>>> In order to fix this, let's relocate checksum_value's position >>>>> to the head of sit_nat_version_bitmap as below, then nat/sit >>>>> bitmap and chksum value update will become safe. >>>>> >>>>> After: >>>>> >>>>> struct f2fs_checkpoint layout: >>>>> +--------------------------+ 0x0000 >>>>> | checkpoint_ver | >>>>> | ...... | >>>>> | checksum_offset |------+ >>>>> | ...... | | >>>>> | sit_nat_version_bitmap[] |<-----+ >>>>> | ...... |<-------------+ >>>>> | | | >>>>> +--------------------------+ 0x1000 | >>>>> | | nat_bitmap + sit_bitmap >>>>> | payload blocks | | >>>>> | | | >>>>> +--------------------------|<-------------+ >>>>> >>>>> Related report and discussion: >>>>> >>>>> https://sourceforge.net/p/linux-f2fs/mailman/message/36642346/ >>>>> >>>>> In addition, during writing checkpoint, if large_nat_bitmap feature is >>>>> enabled, we need to set CP_LARGE_NAT_BITMAP_FLAG flag in checkpoint. >>>>> >>>>> Reported-by: Park Ju Hyung <qkrwngud...@gmail.com> >>>>> Signed-off-by: Chao Yu <yuch...@huawei.com> >>>>> --- >>>>> v3: >>>>> - if large_nat_bitmap is off, fix to configure checksum_offset to >>>>> CP_CHKSUM_OFFSET. >>>>> fsck/f2fs.h | 9 ++++++++- >>>>> fsck/fsck.c | 37 +++++++++++++++++++++++++++++++++++++ >>>>> fsck/fsck.h | 1 + >>>>> fsck/main.c | 2 ++ >>>>> fsck/mount.c | 9 ++++++++- >>>>> fsck/resize.c | 5 +++++ >>>>> include/f2fs_fs.h | 10 ++++++++-- >>>>> mkfs/f2fs_format.c | 5 ++++- >>>>> 8 files changed, 73 insertions(+), 5 deletions(-) >>>>> >>>>> diff --git a/fsck/f2fs.h b/fsck/f2fs.h >>>>> index 93f01e5..4dc6698 100644 >>>>> --- a/fsck/f2fs.h >>>>> +++ b/fsck/f2fs.h >>>>> @@ -270,9 +270,16 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info >>>>> *sbi, int flag) >>>>> int offset; >>>>> >>>>> if (is_set_ckpt_flags(ckpt, CP_LARGE_NAT_BITMAP_FLAG)) { >>>>> + unsigned int chksum_size = 0; >>>>> + >>>>> offset = (flag == SIT_BITMAP) ? >>>>> le32_to_cpu(ckpt->nat_ver_bitmap_bytesize) : 0; >>>>> - return &ckpt->sit_nat_version_bitmap + offset; >>>>> + >>>>> + if (le32_to_cpu(ckpt->checksum_offset) == >>>>> + CP_MIN_CHKSUM_OFFSET) >>>>> + chksum_size = sizeof(__le32); >>>>> + >>>>> + return &ckpt->sit_nat_version_bitmap + offset + >>>>> chksum_size; >>>>> } >>>>> >>>>> if (le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload) > 0) { >>>>> diff --git a/fsck/fsck.c b/fsck/fsck.c >>>>> index a8c8923..b5daeb4 100644 >>>>> --- a/fsck/fsck.c >>>>> +++ b/fsck/fsck.c >>>>> @@ -1917,6 +1917,19 @@ int fsck_chk_meta(struct f2fs_sb_info *sbi) >>>>> return 0; >>>>> } >>>>> >>>>> +void fsck_chk_checkpoint(struct f2fs_sb_info *sbi) >>>>> +{ >>>>> + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); >>>>> + >>>>> + if (get_cp(ckpt_flags) & CP_LARGE_NAT_BITMAP_FLAG) { >>>>> + if (get_cp(checksum_offset) != CP_MIN_CHKSUM_OFFSET) { >>>>> + ASSERT_MSG("Deprecated layout of large_nat_bitmap, >>>>> " >>>>> + "chksum_offset:%u", >>>>> get_cp(checksum_offset)); >>>>> + c.fix_chksum = 1; >>>>> + } >>>>> + } >>>>> +} >>>>> + >>>>> void fsck_init(struct f2fs_sb_info *sbi) >>>>> { >>>>> struct f2fs_fsck *fsck = F2FS_FSCK(sbi); >>>>> @@ -2017,6 +2030,23 @@ static void flush_curseg_sit_entries(struct >>>>> f2fs_sb_info *sbi) >>>>> free(sit_blk); >>>>> } >>>>> >>>>> +static void fix_checksum(struct f2fs_sb_info *sbi) >>>>> +{ >>>>> + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); >>>>> + struct f2fs_nm_info *nm_i = NM_I(sbi); >>>>> + struct sit_info *sit_i = SIT_I(sbi); >>>>> + void *bitmap_offset; >>>>> + >>>>> + if (!c.fix_chksum) >>>>> + return; >>>>> + >>>>> + bitmap_offset = cp->sit_nat_version_bitmap + sizeof(__le32); >>>>> + >>>>> + memcpy(bitmap_offset, nm_i->nat_bitmap, nm_i->bitmap_size); >>>>> + memcpy(bitmap_offset + nm_i->bitmap_size, >>>>> + sit_i->sit_bitmap, sit_i->bitmap_size); >>>>> +} >>>>> + >>>>> static void fix_checkpoint(struct f2fs_sb_info *sbi) >>>>> { >>>>> struct f2fs_fsck *fsck = F2FS_FSCK(sbi); >>>>> @@ -2038,6 +2068,12 @@ static void fix_checkpoint(struct f2fs_sb_info >>>>> *sbi) >>>>> flags |= CP_TRIMMED_FLAG; >>>>> if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG)) >>>>> flags |= CP_DISABLED_FLAG; >>>>> + if (is_set_ckpt_flags(cp, CP_LARGE_NAT_BITMAP_FLAG)) { >>>>> + flags |= CP_LARGE_NAT_BITMAP_FLAG; >>>>> + set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET); >>>>> + } else { >>>>> + set_cp(checksum_offset, CP_CHKSUM_OFFSET); >>>>> + } >>>>> >>>>> if (flags & CP_UMOUNT_FLAG) >>>>> cp_blocks = 8; >>>>> @@ -2717,6 +2753,7 @@ int fsck_verify(struct f2fs_sb_info *sbi) >>>>> write_curseg_info(sbi); >>>>> flush_curseg_sit_entries(sbi); >>>>> } >>>>> + fix_checksum(sbi); >>>>> fix_checkpoint(sbi); >>>>> } else if (is_set_ckpt_flags(cp, CP_FSCK_FLAG) || >>>>> is_set_ckpt_flags(cp, CP_QUOTA_NEED_FSCK_FLAG)) { >>>>> diff --git a/fsck/fsck.h b/fsck/fsck.h >>>>> index cbd6e93..c8802b0 100644 >>>>> --- a/fsck/fsck.h >>>>> +++ b/fsck/fsck.h >>>>> @@ -154,6 +154,7 @@ extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, >>>>> u32, struct child_info *, >>>>> int, int); >>>>> int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *, >>>>> struct child_info *); >>>>> +void fsck_chk_checkpoint(struct f2fs_sb_info *sbi); >>>>> int fsck_chk_meta(struct f2fs_sb_info *sbi); >>>>> int fsck_chk_curseg_info(struct f2fs_sb_info *); >>>>> int convert_encrypted_name(unsigned char *, u32, unsigned char *, int); >>>>> diff --git a/fsck/main.c b/fsck/main.c >>>>> index 03076d9..afdfec9 100644 >>>>> --- a/fsck/main.c >>>>> +++ b/fsck/main.c >>>>> @@ -616,6 +616,8 @@ static void do_fsck(struct f2fs_sb_info *sbi) >>>>> c.fix_on = 1; >>>>> } >>>>> >>>>> + fsck_chk_checkpoint(sbi); >>>>> + >>>>> fsck_chk_quota_node(sbi); >>>>> >>>>> /* Traverse all block recursively from root inode */ >>>>> diff --git a/fsck/mount.c b/fsck/mount.c >>>>> index 95c5357..5a0955e 100644 >>>>> --- a/fsck/mount.c >>>>> +++ b/fsck/mount.c >>>>> @@ -774,7 +774,8 @@ static int verify_checksum_chksum(struct >>>>> f2fs_checkpoint *cp) >>>>> unsigned int chksum_offset = get_cp(checksum_offset); >>>>> unsigned int crc, cal_crc; >>>>> >>>>> - if (chksum_offset > CP_CHKSUM_OFFSET) { >>>>> + if (chksum_offset < CP_MIN_CHKSUM_OFFSET || >>>>> + chksum_offset > CP_CHKSUM_OFFSET) { >>>>> MSG(0, "\tInvalid CP CRC offset: %u\n", chksum_offset); >>>>> return -1; >>>>> } >>>>> @@ -2372,6 +2373,12 @@ void write_checkpoint(struct f2fs_sb_info *sbi) >>>>> flags |= CP_TRIMMED_FLAG; >>>>> if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG)) >>>>> flags |= CP_DISABLED_FLAG; >>>>> + if (is_set_ckpt_flags(cp, CP_LARGE_NAT_BITMAP_FLAG)) { >>>>> + flags |= CP_LARGE_NAT_BITMAP_FLAG; >>>>> + set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET); >>>>> + } else { >>>>> + set_cp(checksum_offset, CP_CHKSUM_OFFSET); >>>>> + } >>>>> >>>>> set_cp(free_segment_count, get_free_segments(sbi)); >>>>> set_cp(valid_block_count, sbi->total_valid_block_count); >>>>> diff --git a/fsck/resize.c b/fsck/resize.c >>>>> index 5537a73..fc563f2 100644 >>>>> --- a/fsck/resize.c >>>>> +++ b/fsck/resize.c >>>>> @@ -514,6 +514,11 @@ static void rebuild_checkpoint(struct f2fs_sb_info >>>>> *sbi, >>>>> flags = update_nat_bits_flags(new_sb, cp, get_cp(ckpt_flags)); >>>>> if (flags & CP_COMPACT_SUM_FLAG) >>>>> flags &= ~CP_COMPACT_SUM_FLAG; >>>>> + if (flags & CP_LARGE_NAT_BITMAP_FLAG) >>>>> + set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET); >>>>> + else >>>>> + set_cp(checksum_offset, CP_CHKSUM_OFFSET); >>>>> + >>>>> set_cp(ckpt_flags, flags); >>>>> >>>>> memcpy(new_cp, cp, (unsigned char *)cp->sit_nat_version_bitmap - >>>>> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h >>>>> index e0a4cbf..84a4e55 100644 >>>>> --- a/include/f2fs_fs.h >>>>> +++ b/include/f2fs_fs.h >>>>> @@ -382,6 +382,7 @@ struct f2fs_configuration { >>>>> int ro; >>>>> int preserve_limits; /* preserve quota limits */ >>>>> int large_nat_bitmap; >>>>> + int fix_chksum; /* fix old cp.chksum position */ >>>>> __le32 feature; /* defined features */ >>>>> >>>>> /* mkfs parameters */ >>>>> @@ -692,10 +693,15 @@ struct f2fs_checkpoint { >>>>> unsigned char sit_nat_version_bitmap[1]; >>>>> } __attribute__((packed)); >>>>> >>>>> +#define CP_BITMAP_OFFSET \ >>>>> + (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap)) >>>>> +#define CP_MIN_CHKSUM_OFFSET CP_BITMAP_OFFSET >>>>> + >>>>> +#define MIN_NAT_BITMAP_SIZE 64 >>>>> #define MAX_SIT_BITMAP_SIZE_IN_CKPT \ >>>>> - (CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - 64) >>>>> + (CP_CHKSUM_OFFSET - CP_BITMAP_OFFSET - MIN_NAT_BITMAP_SIZE) >>>>> #define MAX_BITMAP_SIZE_IN_CKPT \ >>>>> - (CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1) >>>>> + (CP_CHKSUM_OFFSET - CP_BITMAP_OFFSET) >>>>> >>>>> /* >>>>> * For orphan inode management >>>>> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c >>>>> index ab8103c..ed27700 100644 >>>>> --- a/mkfs/f2fs_format.c >>>>> +++ b/mkfs/f2fs_format.c >>>>> @@ -690,7 +690,10 @@ static int f2fs_write_check_point_pack(void) >>>>> set_cp(nat_ver_bitmap_bytesize, ((get_sb(segment_count_nat) / 2) >>>>> << >>>>> get_sb(log_blocks_per_seg)) / 8); >>>>> >>>>> - set_cp(checksum_offset, CP_CHKSUM_OFFSET); >>>>> + if (c.large_nat_bitmap) >>>>> + set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET); >>>>> + else >>>>> + set_cp(checksum_offset, CP_CHKSUM_OFFSET); >>>>> >>>>> crc = f2fs_checkpoint_chksum(cp); >>>>> *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) = >>>>> -- >>>>> 2.18.0.rc1 >>>>> >>>>> >>>>> >>>>> _______________________________________________ >>>>> Linux-f2fs-devel mailing list >>>>> Linux-f2fs-devel@lists.sourceforge.net >>>>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel >>>>> >>>> > . > _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel