Add a helper function ext4_inode_bitmap_csum_set_fast() that uses crc32c_flip_range() to incrementally update the inode bitmap checksum after flipping a single bit at the given offset. This avoids a full bitmap CRC rescan, computing the CRC delta in O(log N) time. Signed-off-by: Baokun Li --- fs/ext4/bitmap.c | 23 +++++++++++++++++++++++ fs/ext4/ext4.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index 008acc439301..ea47ca0d7046 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -71,6 +71,29 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_inode_bitmap_csum_store(sb, gdp, csum); } +/* + * Update inode bitmap checksum for a single flipped bit. + * + * Use crc32c_flip_range() to incrementally update the checksum after + * flipping the bit at @offset, avoiding a full bitmap CRC rescan. + * The csum_seed cancels out in the XOR delta, so it is not needed here. + */ +void ext4_inode_bitmap_csum_set_fast(struct super_block *sb, + struct ext4_group_desc *gdp, + ext4_grpblk_t offset) +{ + __u32 new_csum, old_csum; + + if (!ext4_has_feature_metadata_csum(sb)) + return; + + old_csum = ext4_inode_bitmap_csum_get(sb, gdp); + new_csum = crc32c_flip_range(old_csum, EXT4_INODES_PER_GROUP(sb), + offset, 1); + + ext4_inode_bitmap_csum_store(sb, gdp, new_csum); +} + static inline __u32 ext4_block_bitmap_csum_get(struct super_block *sb, struct ext4_group_desc *gdp) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index c423a9a04047..e6739d5af490 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2764,6 +2764,9 @@ extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); void ext4_inode_bitmap_csum_set(struct super_block *sb, struct ext4_group_desc *gdp, struct buffer_head *bh); +void ext4_inode_bitmap_csum_set_fast(struct super_block *sb, + struct ext4_group_desc *gdp, + ext4_grpblk_t offset); int ext4_inode_bitmap_csum_verify(struct super_block *sb, struct ext4_group_desc *gdp, struct buffer_head *bh); -- 2.43.7