diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2012-04-29 18:45:10 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-04-29 18:45:10 -0400 |
commit | feb0ab32a57e4e6c8b24f6fb68f0ce08efe4603c (patch) | |
tree | 6438fc46013c2f5d60e78060c66e2809c6056f1a /fs/ext4 | |
parent | cc8e94fd126ab2d2e4bcb1b65c7316196f0cec8c (diff) |
ext4: make block group checksums use metadata_csum algorithm
metadata_csum supersedes uninit_bg. Convert the ROCOMPAT uninit_bg
flag check to a helper function that covers both, and make the
checksum calculation algorithm use either crc16 or the metadata_csum
chosen algorithm depending on which flag is set. Print a warning if
we try to mount a filesystem with both feature flags set.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/balloc.c | 4 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 6 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 17 | ||||
-rw-r--r-- | fs/ext4/inode.c | 3 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 6 | ||||
-rw-r--r-- | fs/ext4/resize.c | 9 | ||||
-rw-r--r-- | fs/ext4/super.c | 81 |
7 files changed, 76 insertions, 50 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 0a64e4d5dbad..5745d53c67e8 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -168,7 +168,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
168 | 168 | ||
169 | /* If checksum is bad mark all blocks used to prevent allocation | 169 | /* If checksum is bad mark all blocks used to prevent allocation |
170 | * essentially implementing a per-group read-only flag. */ | 170 | * essentially implementing a per-group read-only flag. */ |
171 | if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { | 171 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { |
172 | ext4_error(sb, "Checksum bad for group %u", block_group); | 172 | ext4_error(sb, "Checksum bad for group %u", block_group); |
173 | ext4_free_group_clusters_set(sb, gdp, 0); | 173 | ext4_free_group_clusters_set(sb, gdp, 0); |
174 | ext4_free_inodes_set(sb, gdp, 0); | 174 | ext4_free_inodes_set(sb, gdp, 0); |
@@ -214,7 +214,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
214 | sb->s_blocksize * 8, bh->b_data); | 214 | sb->s_blocksize * 8, bh->b_data); |
215 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, | 215 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, |
216 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | 216 | EXT4_BLOCKS_PER_GROUP(sb) / 8); |
217 | gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); | 217 | ext4_group_desc_csum_set(sb, block_group, gdp); |
218 | } | 218 | } |
219 | 219 | ||
220 | /* Return the number of free blocks in a block group. It is used when | 220 | /* Return the number of free blocks in a block group. It is used when |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 57d7c356eaab..84e76bb96070 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2114,10 +2114,10 @@ extern void ext4_used_dirs_set(struct super_block *sb, | |||
2114 | struct ext4_group_desc *bg, __u32 count); | 2114 | struct ext4_group_desc *bg, __u32 count); |
2115 | extern void ext4_itable_unused_set(struct super_block *sb, | 2115 | extern void ext4_itable_unused_set(struct super_block *sb, |
2116 | struct ext4_group_desc *bg, __u32 count); | 2116 | struct ext4_group_desc *bg, __u32 count); |
2117 | extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, | 2117 | extern int ext4_group_desc_csum_verify(struct super_block *sb, __u32 group, |
2118 | struct ext4_group_desc *gdp); | ||
2119 | extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, | ||
2120 | struct ext4_group_desc *gdp); | 2118 | struct ext4_group_desc *gdp); |
2119 | extern void ext4_group_desc_csum_set(struct super_block *sb, __u32 group, | ||
2120 | struct ext4_group_desc *gdp); | ||
2121 | 2121 | ||
2122 | static inline int ext4_has_group_desc_csum(struct super_block *sb) | 2122 | static inline int ext4_has_group_desc_csum(struct super_block *sb) |
2123 | { | 2123 | { |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index a6383fcb714b..a044a9b77491 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -70,13 +70,11 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb, | |||
70 | ext4_group_t block_group, | 70 | ext4_group_t block_group, |
71 | struct ext4_group_desc *gdp) | 71 | struct ext4_group_desc *gdp) |
72 | { | 72 | { |
73 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
74 | |||
75 | J_ASSERT_BH(bh, buffer_locked(bh)); | 73 | J_ASSERT_BH(bh, buffer_locked(bh)); |
76 | 74 | ||
77 | /* If checksum is bad mark all blocks and inodes use to prevent | 75 | /* If checksum is bad mark all blocks and inodes use to prevent |
78 | * allocation, essentially implementing a per-group read-only flag. */ | 76 | * allocation, essentially implementing a per-group read-only flag. */ |
79 | if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { | 77 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { |
80 | ext4_error(sb, "Checksum bad for group %u", block_group); | 78 | ext4_error(sb, "Checksum bad for group %u", block_group); |
81 | ext4_free_group_clusters_set(sb, gdp, 0); | 79 | ext4_free_group_clusters_set(sb, gdp, 0); |
82 | ext4_free_inodes_set(sb, gdp, 0); | 80 | ext4_free_inodes_set(sb, gdp, 0); |
@@ -92,7 +90,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb, | |||
92 | bh->b_data); | 90 | bh->b_data); |
93 | ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh, | 91 | ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh, |
94 | EXT4_INODES_PER_GROUP(sb) / 8); | 92 | EXT4_INODES_PER_GROUP(sb) / 8); |
95 | gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); | 93 | ext4_group_desc_csum_set(sb, block_group, gdp); |
96 | 94 | ||
97 | return EXT4_INODES_PER_GROUP(sb); | 95 | return EXT4_INODES_PER_GROUP(sb); |
98 | } | 96 | } |
@@ -298,7 +296,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) | |||
298 | } | 296 | } |
299 | ext4_inode_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, | 297 | ext4_inode_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, |
300 | EXT4_INODES_PER_GROUP(sb) / 8); | 298 | EXT4_INODES_PER_GROUP(sb) / 8); |
301 | gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); | 299 | ext4_group_desc_csum_set(sb, block_group, gdp); |
302 | ext4_unlock_group(sb, block_group); | 300 | ext4_unlock_group(sb, block_group); |
303 | 301 | ||
304 | percpu_counter_inc(&sbi->s_freeinodes_counter); | 302 | percpu_counter_inc(&sbi->s_freeinodes_counter); |
@@ -731,7 +729,7 @@ repeat_in_this_group: | |||
731 | 729 | ||
732 | got: | 730 | got: |
733 | /* We may have to initialize the block bitmap if it isn't already */ | 731 | /* We may have to initialize the block bitmap if it isn't already */ |
734 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && | 732 | if (ext4_has_group_desc_csum(sb) && |
735 | gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 733 | gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
736 | struct buffer_head *block_bitmap_bh; | 734 | struct buffer_head *block_bitmap_bh; |
737 | 735 | ||
@@ -757,8 +755,7 @@ got: | |||
757 | block_bitmap_bh, | 755 | block_bitmap_bh, |
758 | EXT4_BLOCKS_PER_GROUP(sb) / | 756 | EXT4_BLOCKS_PER_GROUP(sb) / |
759 | 8); | 757 | 8); |
760 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, | 758 | ext4_group_desc_csum_set(sb, group, gdp); |
761 | gdp); | ||
762 | } | 759 | } |
763 | ext4_unlock_group(sb, group); | 760 | ext4_unlock_group(sb, group); |
764 | 761 | ||
@@ -811,7 +808,7 @@ got: | |||
811 | if (ext4_has_group_desc_csum(sb)) { | 808 | if (ext4_has_group_desc_csum(sb)) { |
812 | ext4_inode_bitmap_csum_set(sb, group, gdp, inode_bitmap_bh, | 809 | ext4_inode_bitmap_csum_set(sb, group, gdp, inode_bitmap_bh, |
813 | EXT4_INODES_PER_GROUP(sb) / 8); | 810 | EXT4_INODES_PER_GROUP(sb) / 8); |
814 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); | 811 | ext4_group_desc_csum_set(sb, group, gdp); |
815 | ext4_unlock_group(sb, group); | 812 | ext4_unlock_group(sb, group); |
816 | } | 813 | } |
817 | 814 | ||
@@ -1181,7 +1178,7 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group, | |||
1181 | skip_zeroout: | 1178 | skip_zeroout: |
1182 | ext4_lock_group(sb, group); | 1179 | ext4_lock_group(sb, group); |
1183 | gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED); | 1180 | gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED); |
1184 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); | 1181 | ext4_group_desc_csum_set(sb, group, gdp); |
1185 | ext4_unlock_group(sb, group); | 1182 | ext4_unlock_group(sb, group); |
1186 | 1183 | ||
1187 | BUFFER_TRACE(group_desc_bh, | 1184 | BUFFER_TRACE(group_desc_bh, |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 16a67359b4c7..7bccdf32a32c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3584,8 +3584,7 @@ make_io: | |||
3584 | b = table; | 3584 | b = table; |
3585 | end = b + EXT4_SB(sb)->s_inode_readahead_blks; | 3585 | end = b + EXT4_SB(sb)->s_inode_readahead_blks; |
3586 | num = EXT4_INODES_PER_GROUP(sb); | 3586 | num = EXT4_INODES_PER_GROUP(sb); |
3587 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3587 | if (ext4_has_group_desc_csum(sb)) |
3588 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | ||
3589 | num -= ext4_itable_unused_count(sb, gdp); | 3588 | num -= ext4_itable_unused_count(sb, gdp); |
3590 | table += num / inodes_per_block; | 3589 | table += num / inodes_per_block; |
3591 | if (end > table) | 3590 | if (end > table) |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 95a388fef397..ccb9c2f527d5 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2799,7 +2799,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2799 | ext4_free_group_clusters_set(sb, gdp, len); | 2799 | ext4_free_group_clusters_set(sb, gdp, len); |
2800 | ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh, | 2800 | ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh, |
2801 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | 2801 | EXT4_BLOCKS_PER_GROUP(sb) / 8); |
2802 | gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp); | 2802 | ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp); |
2803 | 2803 | ||
2804 | ext4_unlock_group(sb, ac->ac_b_ex.fe_group); | 2804 | ext4_unlock_group(sb, ac->ac_b_ex.fe_group); |
2805 | percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len); | 2805 | percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len); |
@@ -4663,7 +4663,7 @@ do_more: | |||
4663 | ext4_free_group_clusters_set(sb, gdp, ret); | 4663 | ext4_free_group_clusters_set(sb, gdp, ret); |
4664 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, | 4664 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, |
4665 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | 4665 | EXT4_BLOCKS_PER_GROUP(sb) / 8); |
4666 | gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); | 4666 | ext4_group_desc_csum_set(sb, block_group, gdp); |
4667 | ext4_unlock_group(sb, block_group); | 4667 | ext4_unlock_group(sb, block_group); |
4668 | percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); | 4668 | percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); |
4669 | 4669 | ||
@@ -4809,7 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, | |||
4809 | ext4_free_group_clusters_set(sb, desc, blk_free_count); | 4809 | ext4_free_group_clusters_set(sb, desc, blk_free_count); |
4810 | ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh, | 4810 | ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh, |
4811 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | 4811 | EXT4_BLOCKS_PER_GROUP(sb) / 8); |
4812 | desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); | 4812 | ext4_group_desc_csum_set(sb, block_group, desc); |
4813 | ext4_unlock_group(sb, block_group); | 4813 | ext4_unlock_group(sb, block_group); |
4814 | percpu_counter_add(&sbi->s_freeclusters_counter, | 4814 | percpu_counter_add(&sbi->s_freeclusters_counter, |
4815 | EXT4_B2C(sbi, blocks_freed)); | 4815 | EXT4_B2C(sbi, blocks_freed)); |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index dc597e066308..a58ce7c507ae 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -1160,7 +1160,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, | |||
1160 | EXT4_B2C(sbi, group_data->free_blocks_count)); | 1160 | EXT4_B2C(sbi, group_data->free_blocks_count)); |
1161 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); | 1161 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); |
1162 | gdp->bg_flags = cpu_to_le16(*bg_flags); | 1162 | gdp->bg_flags = cpu_to_le16(*bg_flags); |
1163 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); | 1163 | ext4_group_desc_csum_set(sb, group, gdp); |
1164 | 1164 | ||
1165 | err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); | 1165 | err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); |
1166 | if (unlikely(err)) { | 1166 | if (unlikely(err)) { |
@@ -1399,17 +1399,14 @@ static int ext4_setup_next_flex_gd(struct super_block *sb, | |||
1399 | (1 + ext4_bg_num_gdb(sb, group + i) + | 1399 | (1 + ext4_bg_num_gdb(sb, group + i) + |
1400 | le16_to_cpu(es->s_reserved_gdt_blocks)) : 0; | 1400 | le16_to_cpu(es->s_reserved_gdt_blocks)) : 0; |
1401 | group_data[i].free_blocks_count = blocks_per_group - overhead; | 1401 | group_data[i].free_blocks_count = blocks_per_group - overhead; |
1402 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 1402 | if (ext4_has_group_desc_csum(sb)) |
1403 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | ||
1404 | flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT | | 1403 | flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT | |
1405 | EXT4_BG_INODE_UNINIT; | 1404 | EXT4_BG_INODE_UNINIT; |
1406 | else | 1405 | else |
1407 | flex_gd->bg_flags[i] = EXT4_BG_INODE_ZEROED; | 1406 | flex_gd->bg_flags[i] = EXT4_BG_INODE_ZEROED; |
1408 | } | 1407 | } |
1409 | 1408 | ||
1410 | if (last_group == n_group && | 1409 | if (last_group == n_group && ext4_has_group_desc_csum(sb)) |
1411 | EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
1412 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | ||
1413 | /* We need to initialize block bitmap of last group. */ | 1410 | /* We need to initialize block bitmap of last group. */ |
1414 | flex_gd->bg_flags[i - 1] &= ~EXT4_BG_BLOCK_UNINIT; | 1411 | flex_gd->bg_flags[i - 1] &= ~EXT4_BG_BLOCK_UNINIT; |
1415 | 1412 | ||
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, | 1955 | static __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 | |||
1995 | out: | ||
1978 | return cpu_to_le16(crc); | 1996 | return cpu_to_le16(crc); |
1979 | } | 1997 | } |
1980 | 1998 | ||
1981 | int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 block_group, | 1999 | int 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 | ||
2010 | void 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 */ |
1993 | static int ext4_check_descriptors(struct super_block *sb, | 2019 | static 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)), |