From 11149fa1150052e70010ac7e583eb28470a7413f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=20Brant=C3=A9n?= Date: Wed, 5 Feb 2020 23:47:39 +0100 Subject: [PATCH] more work on inode checksums --- Ext4Fsd/ext4/ext4_csum.c | 40 +++++++++++++++++------------------- Ext4Fsd/include/linux/ext4.h | 13 ++++++------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/Ext4Fsd/ext4/ext4_csum.c b/Ext4Fsd/ext4/ext4_csum.c index eaf3342..cb27fb7 100644 --- a/Ext4Fsd/ext4/ext4_csum.c +++ b/Ext4Fsd/ext4/ext4_csum.c @@ -370,7 +370,7 @@ static __le32 ext4_inode_csum_seed(struct inode *inode) } static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, - struct ext4_inode_info *ei) + struct ext4_inode_info *unused) { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); __u32 csum; @@ -378,7 +378,8 @@ static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, int offset = offsetof(struct ext4_inode, i_checksum_lo); unsigned int csum_size = sizeof(dummy_csum); - csum = ext4_chksum(sbi, ext4_inode_csum_seed(inode), (__u8 *)raw, offset); + csum = ext4_inode_csum_seed(inode); + csum = ext4_chksum(sbi, csum, (__u8 *)raw, offset); csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, csum_size); offset += csum_size; csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset, @@ -389,7 +390,7 @@ static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, csum = ext4_chksum(sbi, csum, (__u8 *)raw + EXT4_GOOD_OLD_INODE_SIZE, offset - EXT4_GOOD_OLD_INODE_SIZE); - if (EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) { + if (offsetof(struct ext4_inode, i_checksum_hi) + sizeof(raw->i_checksum_hi) <= EXT4_GOOD_OLD_INODE_SIZE + raw->i_extra_isize) { csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, csum_size); offset += csum_size; @@ -402,45 +403,42 @@ static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, } int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw, - struct ext4_inode_info *ei) + struct ext4_inode_info *unused) { - __u32 provided, calculated, isz; + __u32 provided, calculated; - if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != - cpu_to_le32(EXT4_OS_LINUX) || - !ext4_has_feature_metadata_csum(inode->i_sb)) + if (!ext4_has_metadata_csum(inode->i_sb)) return 1; provided = le16_to_cpu(raw->i_checksum_lo); - calculated = ext4_inode_csum(inode, raw, ei); + calculated = ext4_inode_csum(inode, raw, unused); if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE && - EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) - {provided |= ((__u32)le16_to_cpu(raw->i_checksum_hi)) << 16;isz=EXT4_INODE_SIZE(inode->i_sb);} + offsetof(struct ext4_inode, i_checksum_hi) + sizeof(raw->i_checksum_hi) <= EXT4_GOOD_OLD_INODE_SIZE + raw->i_extra_isize) + provided |= ((__u32)le16_to_cpu(raw->i_checksum_hi)) << 16; else - {calculated &= 0xFFFF;isz=EXT4_GOOD_OLD_INODE_SIZE;} + calculated &= 0xFFFF; - if (provided != calculated) { - DbgPrint("inod %d checksum invalid: %lx!=%lx, isz=%u\n", inode->i_ino, provided, calculated, isz); - } + if (provided != calculated) + DbgPrint("checksum verify failed on inode %u: %lx != %lx\n", inode->i_ino, provided, calculated); return provided == calculated; } void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw, - struct ext4_inode_info *ei) + struct ext4_inode_info *unused) { __u32 csum; - if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != - cpu_to_le32(EXT4_OS_LINUX) || - !ext4_has_feature_metadata_csum(inode->i_sb)) + if (!ext4_has_metadata_csum(inode->i_sb)) return; - csum = ext4_inode_csum(inode, raw, ei); + csum = ext4_inode_csum(inode, raw, unused); raw->i_checksum_lo = cpu_to_le16(csum & 0xFFFF); if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE && - EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) + offsetof(struct ext4_inode, i_checksum_hi) + sizeof(raw->i_checksum_hi) <= EXT4_GOOD_OLD_INODE_SIZE + raw->i_extra_isize) raw->i_checksum_hi = cpu_to_le16(csum >> 16); + DbgPrint("set checksum on inode %u: csum == %lx\n", inode->i_ino, csum); + ext4_inode_csum_verify(inode, raw, unused); } /* diff --git a/Ext4Fsd/include/linux/ext4.h b/Ext4Fsd/include/linux/ext4.h index 454b8e9..70d58db 100644 --- a/Ext4Fsd/include/linux/ext4.h +++ b/Ext4Fsd/include/linux/ext4.h @@ -962,7 +962,7 @@ struct move_extent { #define EXT4_EPOCH_BITS 2 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS) - +#if 0 /* * Extended fields will fit into an inode if the filesystem was formatted * with large inodes (-I 256 or larger) and there are not currently any EAs @@ -973,12 +973,13 @@ struct move_extent { * This macro checks if a certain field fits in the inode. Note that * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize */ -/*#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \ +#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \ ((offsetof(typeof(*ext4_inode), field) + \ sizeof((ext4_inode)->field)) \ <= (EXT4_GOOD_OLD_INODE_SIZE + \ - (einode)->i_extra_isize))*/ -#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) 1 + (einode)->i_extra_isize)) \ + +#endif /* * We use an encoding that preserves the times for extra epoch "00": * @@ -1026,7 +1027,7 @@ static inline void ext4_decode_extra_time(struct timespec64 *time, } time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; } - +#if 0 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \ do { \ (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \ @@ -1070,7 +1071,7 @@ do { \ else \ (einode)->xtime.tv_nsec = 0; \ } while (0) - +#endif #define i_disk_version osd1.linux1.l_i_version #if defined(__KERNEL__) || defined(__linux__)