aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c81
1 files changed, 57 insertions, 24 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f80c7e612829..c18c5968cd96 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1952,43 +1952,69 @@ failed:
1952 return 0; 1952 return 0;
1953} 1953}
1954 1954
1955__le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, 1955static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
1956 struct ext4_group_desc *gdp) 1956 struct ext4_group_desc *gdp)
1957{ 1957{
1958 int offset;
1958 __u16 crc = 0; 1959 __u16 crc = 0;
1960 __le32 le_group = cpu_to_le32(block_group);
1959 1961
1960 if (sbi->s_es->s_feature_ro_compat & 1962 if ((sbi->s_es->s_feature_ro_compat &
1961 cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 1963 cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))) {
1962 int offset = offsetof(struct ext4_group_desc, bg_checksum); 1964 /* Use new metadata_csum algorithm */
1963 __le32 le_group = cpu_to_le32(block_group); 1965 __u16 old_csum;
1964 1966 __u32 csum32;
1965 crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid)); 1967
1966 crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group)); 1968 old_csum = gdp->bg_checksum;
1967 crc = crc16(crc, (__u8 *)gdp, offset); 1969 gdp->bg_checksum = 0;
1968 offset += sizeof(gdp->bg_checksum); /* skip checksum */ 1970 csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
1969 /* for checksum of struct ext4_group_desc do the rest...*/ 1971 sizeof(le_group));
1970 if ((sbi->s_es->s_feature_incompat & 1972 csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp,
1971 cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) && 1973 sbi->s_desc_size);
1972 offset < le16_to_cpu(sbi->s_es->s_desc_size)) 1974 gdp->bg_checksum = old_csum;
1973 crc = crc16(crc, (__u8 *)gdp + offset, 1975
1974 le16_to_cpu(sbi->s_es->s_desc_size) - 1976 crc = csum32 & 0xFFFF;
1975 offset); 1977 goto out;
1976 } 1978 }
1977 1979
1980 /* old crc16 code */
1981 offset = offsetof(struct ext4_group_desc, bg_checksum);
1982
1983 crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
1984 crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
1985 crc = crc16(crc, (__u8 *)gdp, offset);
1986 offset += sizeof(gdp->bg_checksum); /* skip checksum */
1987 /* for checksum of struct ext4_group_desc do the rest...*/
1988 if ((sbi->s_es->s_feature_incompat &
1989 cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
1990 offset < le16_to_cpu(sbi->s_es->s_desc_size))
1991 crc = crc16(crc, (__u8 *)gdp + offset,
1992 le16_to_cpu(sbi->s_es->s_desc_size) -
1993 offset);
1994
1995out:
1978 return cpu_to_le16(crc); 1996 return cpu_to_le16(crc);
1979} 1997}
1980 1998
1981int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 block_group, 1999int ext4_group_desc_csum_verify(struct super_block *sb, __u32 block_group,
1982 struct ext4_group_desc *gdp) 2000 struct ext4_group_desc *gdp)
1983{ 2001{
1984 if ((sbi->s_es->s_feature_ro_compat & 2002 if (ext4_has_group_desc_csum(sb) &&
1985 cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) && 2003 (gdp->bg_checksum != ext4_group_desc_csum(EXT4_SB(sb),
1986 (gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp))) 2004 block_group, gdp)))
1987 return 0; 2005 return 0;
1988 2006
1989 return 1; 2007 return 1;
1990} 2008}
1991 2009
2010void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
2011 struct ext4_group_desc *gdp)
2012{
2013 if (!ext4_has_group_desc_csum(sb))
2014 return;
2015 gdp->bg_checksum = ext4_group_desc_csum(EXT4_SB(sb), block_group, gdp);
2016}
2017
1992/* Called at mount-time, super-block is locked */ 2018/* Called at mount-time, super-block is locked */
1993static int ext4_check_descriptors(struct super_block *sb, 2019static int ext4_check_descriptors(struct super_block *sb,
1994 ext4_group_t *first_not_zeroed) 2020 ext4_group_t *first_not_zeroed)
@@ -2043,7 +2069,7 @@ static int ext4_check_descriptors(struct super_block *sb,
2043 return 0; 2069 return 0;
2044 } 2070 }
2045 ext4_lock_group(sb, i); 2071 ext4_lock_group(sb, i);
2046 if (!ext4_group_desc_csum_verify(sbi, i, gdp)) { 2072 if (!ext4_group_desc_csum_verify(sb, i, gdp)) {
2047 ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " 2073 ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2048 "Checksum for group %u failed (%u!=%u)", 2074 "Checksum for group %u failed (%u!=%u)",
2049 i, le16_to_cpu(ext4_group_desc_csum(sbi, i, 2075 i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
@@ -3069,6 +3095,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3069 goto cantfind_ext4; 3095 goto cantfind_ext4;
3070 sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written); 3096 sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written);
3071 3097
3098 /* Warn if metadata_csum and gdt_csum are both set. */
3099 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
3100 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
3101 EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
3102 ext4_warning(sb, KERN_INFO "metadata_csum and uninit_bg are "
3103 "redundant flags; please run fsck.");
3104
3072 /* Check for a known checksum algorithm */ 3105 /* Check for a known checksum algorithm */
3073 if (!ext4_verify_csum_type(sb, es)) { 3106 if (!ext4_verify_csum_type(sb, es)) {
3074 ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with " 3107 ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
@@ -4400,7 +4433,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4400 struct ext4_group_desc *gdp = 4433 struct ext4_group_desc *gdp =
4401 ext4_get_group_desc(sb, g, NULL); 4434 ext4_get_group_desc(sb, g, NULL);
4402 4435
4403 if (!ext4_group_desc_csum_verify(sbi, g, gdp)) { 4436 if (!ext4_group_desc_csum_verify(sb, g, gdp)) {
4404 ext4_msg(sb, KERN_ERR, 4437 ext4_msg(sb, KERN_ERR,
4405 "ext4_remount: Checksum for group %u failed (%u!=%u)", 4438 "ext4_remount: Checksum for group %u failed (%u!=%u)",
4406 g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)), 4439 g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),