Author: fsu Date: Sun May 13 19:29:35 2018 New Revision: 333585 URL: https://svnweb.freebsd.org/changeset/base/333585
Log: Fix on-disk inode checksum calculation logic. Reviewed by: pfg MFC after: 3 months Differential Revision: https://reviews.freebsd.org/D15395 Modified: head/sys/fs/ext2fs/ext2_csum.c head/sys/fs/ext2fs/ext2_inode_cnv.c Modified: head/sys/fs/ext2fs/ext2_csum.c ============================================================================== --- head/sys/fs/ext2fs/ext2_csum.c Sun May 13 19:19:10 2018 (r333584) +++ head/sys/fs/ext2fs/ext2_csum.c Sun May 13 19:29:35 2018 (r333585) @@ -535,29 +535,42 @@ static uint32_t ext2_ei_csum(struct inode *ip, struct ext2fs_dinode *ei) { struct m_ext2fs *fs; - uint16_t old_hi; - uint32_t inum, gen, crc; + uint32_t inode_csum_seed, inum, gen, crc; + uint16_t dummy_csum = 0; + unsigned int offset, csum_size; fs = ip->i_e2fs; - - ei->e2di_chksum_lo = 0; - if ((EXT2_INODE_SIZE(ip->i_e2fs) > E2FS_REV0_INODE_SIZE && - ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) { - old_hi = ei->e2di_chksum_hi; - ei->e2di_chksum_hi = 0; - } - + offset = offsetof(struct ext2fs_dinode, e2di_chksum_lo); + csum_size = sizeof(dummy_csum); inum = ip->i_number; gen = ip->i_gen; + crc = calculate_crc32c(fs->e2fs_csum_seed, + (uint8_t *)&inum, sizeof(inum)); + inode_csum_seed = calculate_crc32c(crc, + (uint8_t *)&gen, sizeof(gen)); - crc = calculate_crc32c(fs->e2fs_csum_seed, (uint8_t *)&inum, sizeof(inum)); - crc = calculate_crc32c(crc, (uint8_t *)&gen, sizeof(gen)); - crc = calculate_crc32c(crc, (uint8_t *)ei, fs->e2fs->e2fs_inode_size); + crc = calculate_crc32c(inode_csum_seed, (uint8_t *)ei, offset); + crc = calculate_crc32c(crc, (uint8_t *)&dummy_csum, csum_size); + offset += csum_size; + crc = calculate_crc32c(crc, (uint8_t *)ei + offset, + E2FS_REV0_INODE_SIZE - offset); - if ((EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE && - ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) - ei->e2di_chksum_hi = old_hi; + if (EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE) { + offset = offsetof(struct ext2fs_dinode, e2di_chksum_hi); + crc = calculate_crc32c(crc, (uint8_t *)ei + + E2FS_REV0_INODE_SIZE, offset - E2FS_REV0_INODE_SIZE); + if ((EXT2_INODE_SIZE(ip->i_e2fs) > E2FS_REV0_INODE_SIZE && + ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) { + crc = calculate_crc32c(crc, (uint8_t *)&dummy_csum, + csum_size); + offset += csum_size; + } + + crc = calculate_crc32c(crc, (uint8_t *)ei + offset, + EXT2_INODE_SIZE(fs) - offset); + } + return (crc); } @@ -573,10 +586,6 @@ ext2_ei_csum_verify(struct inode *ip, struct ext2fs_di if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) return (0); - /* Check case, when dinode was not initialized */ - if (!memcmp(ei, &ei_zero, sizeof(struct ext2fs_dinode))) - return (0); - provided = ei->e2di_chksum_lo; calculated = ext2_ei_csum(ip, ei); @@ -587,8 +596,17 @@ ext2_ei_csum_verify(struct inode *ip, struct ext2fs_di } else calculated &= 0xFFFF; - if (provided != calculated) + if (provided != calculated) { + /* + * If it is first time used dinode, + * it is expected that it will be zeroed + * and we will not return checksum error in this case. + */ + if (!memcmp(ei, &ei_zero, sizeof(struct ext2fs_dinode))) + return (0); + return (EIO); + } return (0); } Modified: head/sys/fs/ext2fs/ext2_inode_cnv.c ============================================================================== --- head/sys/fs/ext2fs/ext2_inode_cnv.c Sun May 13 19:19:10 2018 (r333584) +++ head/sys/fs/ext2fs/ext2_inode_cnv.c Sun May 13 19:29:35 2018 (r333585) @@ -92,10 +92,7 @@ ext2_print_inode(struct inode *in) int ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip) { - struct m_ext2fs *fs; - const static struct ext2fs_dinode ei_zero; - fs = ip->i_e2fs; ip->i_nlink = ei->e2di_nlink; /* * Godmar thinks - if the link count is zero, then the inode is @@ -139,11 +136,7 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip) memcpy(ip->i_data, ei->e2di_blocks, sizeof(ei->e2di_blocks)); - if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM) && - memcmp(ei, &ei_zero, EXT2_INODE_SIZE(fs))) - return (ext2_ei_csum_verify(ip, ei)); - - return (0); + return (ext2_ei_csum_verify(ip, ei)); } /* _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"