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)
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);
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)
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);
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)
* 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);
}
(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 */
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 *);
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
*/
* 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;
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);
*/
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",