1 ext4: check s_chksum_driver when looking for bg csum presence
3 From: "Darrick J. Wong" <darrick.wong@oracle.com>
5 Convert the ext4_has_group_desc_csum predicate to look for a checksum
6 driver instead of the metadata_csum flag and change the bg checksum
7 calculation function to look for GDT_CSUM before taking the crc16
10 Without this patch, if we mount with ^uninit_bg,^metadata_csum and
11 later metadata_csum gets turned on by accident, the block group
12 checksum functions will incorrectly assume that checksumming is
13 enabled (metadata_csum) but that crc16 should be used
14 (!s_chksum_driver). This is totally wrong, so fix the predicate
15 and the checksum formula selection.
17 (Granted, if the metadata_csum feature bit gets enabled on a live FS
18 then something underhanded is going on, but we could at least avoid
19 writing garbage into the on-disk fields.)
21 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
22 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
23 Reviewed-by: Dmitry Monakhov <dmonakhov@openvz.org>
24 Cc: stable@vger.kernel.org
26 fs/ext4/ext4.h | 4 ++--
27 fs/ext4/super.c | 4 ++++
28 2 files changed, 6 insertions(+), 2 deletions(-)
30 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
31 index fb6aadf..db38ca0f 100644
34 @@ -2367,8 +2367,8 @@ extern int ext4_register_li_request(struct super_block *sb,
35 static inline int ext4_has_group_desc_csum(struct super_block *sb)
37 return EXT4_HAS_RO_COMPAT_FEATURE(sb,
38 - EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
39 - EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
40 + EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
41 + (EXT4_SB(sb)->s_chksum_driver != NULL);
44 static inline int ext4_has_metadata_csum(struct super_block *sb)
45 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
46 index 6ae47d4..de38a96 100644
49 @@ -2032,6 +2032,10 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
53 + if (!(sbi->s_es->s_feature_ro_compat &
54 + cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
57 offset = offsetof(struct ext4_group_desc, bg_checksum);
59 crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));