Previously, f2fs_checkpoint.checksum_offset points fixed position of f2fs_checkpoint structure:
"#define CP_CHKSUM_OFFSET 4092" It is unnecessary, and it breaks the consecutiveness of nat and sit bitmap stored across checkpoint park block and payload blocks. This patch allows f2fs-tools to handle unfixed .checksum_offset. In addition, for the case checksum value is stored in the middle of checkpoint park, calculating checksum value with superposition method like we did for inode_checksum. In addition, add below change: - using MAX_BITMAP_SIZE_IN_CKPT to clean up codes. - introduce verify_checksum_chksum() to verify chksum_{offset,value} Signed-off-by: Chao Yu <yuch...@huawei.com> --- v3: - pass "new_cp" to f2fs_checkpoint_chksum() instead of "cp" in rebuild_checkpoint(). fsck/fsck.c | 5 +++-- fsck/mount.c | 42 +++++++++++++++++++++++++----------------- fsck/resize.c | 10 +++++----- include/f2fs_fs.h | 1 + lib/libf2fs.c | 14 ++++++++++++++ mkfs/f2fs_format.c | 16 +++++++--------- 6 files changed, 55 insertions(+), 33 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 3b54878..a8c8923 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -2056,8 +2056,9 @@ static void fix_checkpoint(struct f2fs_sb_info *sbi) set_cp(valid_node_count, fsck->chk.valid_node_cnt); set_cp(valid_inode_count, fsck->chk.valid_inode_cnt); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CP_CHKSUM_OFFSET); - *((__le32 *)((unsigned char *)cp + CP_CHKSUM_OFFSET)) = cpu_to_le32(crc); + crc = f2fs_checkpoint_chksum(cp); + *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) = + cpu_to_le32(crc); cp_blk_no = get_sb(cp_blkaddr); if (sbi->cur_cp == 2) diff --git a/fsck/mount.c b/fsck/mount.c index aa64e93..95c5357 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -769,15 +769,32 @@ int init_sb_info(struct f2fs_sb_info *sbi) return 0; } +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) { + MSG(0, "\tInvalid CP CRC offset: %u\n", chksum_offset); + return -1; + } + + crc = le32_to_cpu(*(__le32 *)((unsigned char *)cp + chksum_offset)); + cal_crc = f2fs_checkpoint_chksum(cp); + if (cal_crc != crc) { + MSG(0, "\tInvalid CP CRC: offset:%u, crc:0x%x, calc:0x%x\n", + chksum_offset, crc, cal_crc); + return -1; + } + return 0; +} + void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned long long *version) { void *cp_page_1, *cp_page_2; struct f2fs_checkpoint *cp; - unsigned long blk_size = sbi->blocksize; unsigned long long cur_version = 0, pre_version = 0; - unsigned int crc = 0; - size_t crc_offset; /* Read the 1st cp block in this CP pack */ cp_page_1 = malloc(PAGE_SIZE); @@ -787,12 +804,7 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, goto invalid_cp1; cp = (struct f2fs_checkpoint *)cp_page_1; - crc_offset = get_cp(checksum_offset); - if (crc_offset > (blk_size - sizeof(__le32))) - goto invalid_cp1; - - crc = le32_to_cpu(*(__le32 *)((unsigned char *)cp + crc_offset)); - if (f2fs_crc_valid(crc, cp, crc_offset)) + if (verify_checksum_chksum(cp)) goto invalid_cp1; if (get_cp(cp_pack_total_block_count) > sbi->blocks_per_seg) @@ -810,12 +822,7 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, goto invalid_cp2; cp = (struct f2fs_checkpoint *)cp_page_2; - crc_offset = get_cp(checksum_offset); - if (crc_offset > (blk_size - sizeof(__le32))) - goto invalid_cp2; - - crc = le32_to_cpu(*(__le32 *)((unsigned char *)cp + crc_offset)); - if (f2fs_crc_valid(crc, cp, crc_offset)) + if (verify_checksum_chksum(cp)) goto invalid_cp2; cur_version = get_cp(checkpoint_ver); @@ -2373,8 +2380,9 @@ void write_checkpoint(struct f2fs_sb_info *sbi) flags = update_nat_bits_flags(sb, cp, flags); set_cp(ckpt_flags, flags); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CP_CHKSUM_OFFSET); - *((__le32 *)((unsigned char *)cp + CP_CHKSUM_OFFSET)) = cpu_to_le32(crc); + crc = f2fs_checkpoint_chksum(cp); + *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) = + cpu_to_le32(crc); cp_blk_no = get_sb(cp_blkaddr); if (sbi->cur_cp == 2) diff --git a/fsck/resize.c b/fsck/resize.c index 56c8103..5537a73 100644 --- a/fsck/resize.c +++ b/fsck/resize.c @@ -90,11 +90,11 @@ static int get_new_sb(struct f2fs_super_block *sb) * It requires more pages for cp. */ if (max_sit_bitmap_size > MAX_SIT_BITMAP_SIZE_IN_CKPT) { - max_nat_bitmap_size = CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1; + max_nat_bitmap_size = MAX_BITMAP_SIZE_IN_CKPT; set_sb(cp_payload, F2FS_BLK_ALIGN(max_sit_bitmap_size)); } else { - max_nat_bitmap_size = CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - - max_sit_bitmap_size; + max_nat_bitmap_size = MAX_BITMAP_SIZE_IN_CKPT - + max_sit_bitmap_size; set_sb(cp_payload, 0); } @@ -520,8 +520,8 @@ static void rebuild_checkpoint(struct f2fs_sb_info *sbi, (unsigned char *)cp); new_cp->checkpoint_ver = cpu_to_le64(cp_ver + 1); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, new_cp, CP_CHKSUM_OFFSET); - *((__le32 *)((unsigned char *)new_cp + CP_CHKSUM_OFFSET)) = + crc = f2fs_checkpoint_chksum(new_cp); + *((__le32 *)((unsigned char *)new_cp + get_cp(checksum_offset))) = cpu_to_le32(crc); /* Write a new checkpoint in the other set */ diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index b4f992f..e0a4cbf 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -1133,6 +1133,7 @@ extern int utf16_to_utf8(char *, const u_int16_t *, size_t, size_t); extern int log_base_2(u_int32_t); extern unsigned int addrs_per_inode(struct f2fs_inode *); extern __u32 f2fs_inode_chksum(struct f2fs_node *); +extern __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *); extern int get_bits_in_byte(unsigned char n); extern int test_and_set_bit_le(u32, u8 *); diff --git a/lib/libf2fs.c b/lib/libf2fs.c index e0ce029..150e89b 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -532,6 +532,20 @@ __u32 f2fs_inode_chksum(struct f2fs_node *node) return chksum; } +__u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *cp) +{ + unsigned int chksum_ofs = le32_to_cpu(cp->checksum_offset); + __u32 chksum; + + chksum = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, chksum_ofs); + if (chksum_ofs < CP_CHKSUM_OFFSET) { + chksum_ofs += sizeof(chksum); + chksum = f2fs_cal_crc32(chksum, (__u8 *)cp + chksum_ofs, + F2FS_BLKSIZE - chksum_ofs); + } + return chksum; +} + /* * try to identify the root device */ diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index a2685cb..ab8103c 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -342,13 +342,11 @@ static int f2fs_prepare_super_block(void) * It requires more pages for cp. */ if (max_sit_bitmap_size > MAX_SIT_BITMAP_SIZE_IN_CKPT) { - max_nat_bitmap_size = CP_CHKSUM_OFFSET - - sizeof(struct f2fs_checkpoint) + 1; + max_nat_bitmap_size = MAX_BITMAP_SIZE_IN_CKPT; set_sb(cp_payload, F2FS_BLK_ALIGN(max_sit_bitmap_size)); } else { - max_nat_bitmap_size = - CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - - max_sit_bitmap_size; + max_nat_bitmap_size = MAX_BITMAP_SIZE_IN_CKPT - + max_sit_bitmap_size; set_sb(cp_payload, 0); } max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg; @@ -694,8 +692,8 @@ static int f2fs_write_check_point_pack(void) set_cp(checksum_offset, CP_CHKSUM_OFFSET); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CP_CHKSUM_OFFSET); - *((__le32 *)((unsigned char *)cp + CP_CHKSUM_OFFSET)) = + crc = f2fs_checkpoint_chksum(cp); + *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) = cpu_to_le32(crc); blk_size_bytes = 1 << get_sb(log_blocksize); @@ -940,8 +938,8 @@ static int f2fs_write_check_point_pack(void) */ cp->checkpoint_ver = 0; - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CP_CHKSUM_OFFSET); - *((__le32 *)((unsigned char *)cp + CP_CHKSUM_OFFSET)) = + crc = f2fs_checkpoint_chksum(cp); + *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) = cpu_to_le32(crc); cp_seg_blk = get_sb(segment0_blkaddr) + c.blks_per_seg; DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", -- 2.18.0.rc1 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel