Change the block group algorithm to use the same algorithm as the rest of the metadata_csum. This mostly involves providing a helper function to tell if group descriptors should have checksums set or verified, and modifying the gdt checksum code to use the correct algorithm. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- debugfs/debugfs.c | 3 +- lib/ext2fs/alloc.c | 6 +--- lib/ext2fs/alloc_stats.c | 3 +- lib/ext2fs/csum.c | 67 ++++++++++++++++++++++++++++------------------ lib/ext2fs/ext2fs.h | 6 ++++ lib/ext2fs/initialize.c | 3 +- lib/ext2fs/inode.c | 9 ++---- lib/ext2fs/openfs.c | 3 +- lib/ext2fs/rw_bitmaps.c | 12 +++----- misc/dumpe2fs.c | 4 +-- resize/resize2fs.c | 12 +++----- 11 files changed, 66 insertions(+), 62 deletions(-) diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index 36dd730..2e46cd5 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -357,8 +357,7 @@ void do_show_super_stats(int argc, char *argv[]) return; } - gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM); + gdt_csum = ext2fs_has_group_desc_csum(current_fs); for (i = 0; i < current_fs->group_desc_count; i++) { fprintf(out, " Group %2d: block bitmap at %llu, " "inode bitmap at %llu, " diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c index 948a0ec..e62ed68 100644 --- a/lib/ext2fs/alloc.c +++ b/lib/ext2fs/alloc.c @@ -36,8 +36,7 @@ static void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map, blk64_t blk, super_blk, old_desc_blk, new_desc_blk; int old_desc_blocks; - if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) || + if (!ext2fs_has_group_desc_csum(fs) || !(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) return; @@ -83,8 +82,7 @@ static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map, { ext2_ino_t i, ino; - if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) || + if (!ext2fs_has_group_desc_csum(fs) || !(ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT))) return; diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c index adec363..4229084 100644 --- a/lib/ext2fs/alloc_stats.c +++ b/lib/ext2fs/alloc_stats.c @@ -38,8 +38,7 @@ void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, /* We don't strictly need to be clearing the uninit flag if inuse < 0 * (i.e. freeing inodes) but it also means something is bad. */ ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { + if (ext2fs_has_group_desc_csum(fs)) { ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group - ext2fs_bg_itable_unused(fs, group) + group * fs->super->s_inodes_per_group + 1; diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c index 11a24f0..d4f98e0 100644 --- a/lib/ext2fs/csum.c +++ b/lib/ext2fs/csum.c @@ -696,39 +696,56 @@ STATIC __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group) desc = ext2fs_group_desc(fs, fs->group_desc, group); - if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { - size_t offset = offsetof(struct ext2_group_desc, bg_checksum); - #ifdef WORDS_BIGENDIAN - struct ext4_group_desc swabdesc; + struct ext4_group_desc swabdesc; - /* Have to swab back to little-endian to do the checksum */ - memcpy(&swabdesc, desc, size); - ext2fs_swap_group_desc2(fs, - (struct ext2_group_desc *) &swabdesc); - desc = (struct ext2_group_desc *) &swabdesc; + /* Have to swab back to little-endian to do the checksum */ + memcpy(&swabdesc, desc, size); + ext2fs_swap_group_desc2(fs, + (struct ext2_group_desc *) &swabdesc); + desc = (struct ext2_group_desc *) &swabdesc; - group = ext2fs_swab32(group); + group = ext2fs_swab32(group); #endif - crc = ext2fs_crc16(~0, fs->super->s_uuid, - sizeof(fs->super->s_uuid)); - crc = ext2fs_crc16(crc, &group, sizeof(group)); - crc = ext2fs_crc16(crc, desc, offset); - offset += sizeof(desc->bg_checksum); /* skip checksum */ - /* for checksum of struct ext4_group_desc do the rest...*/ - if (offset < size) { - crc = ext2fs_crc16(crc, (char *)desc + offset, - size - offset); - } + + if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { + /* new metadata csum code */ + __u16 old_crc; + __u32 crc32; + + old_crc = desc->bg_checksum; + desc->bg_checksum = 0; + crc32 = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&group, + sizeof(group)); + crc32 = ext2fs_crc32c_le(crc32, (unsigned char *)desc, + size); + desc->bg_checksum = old_crc; + + crc = crc32 & 0xFFFF; + goto out; } + /* old crc16 code */ + size_t offset = offsetof(struct ext2_group_desc, bg_checksum); + crc = ext2fs_crc16(~0, fs->super->s_uuid, + sizeof(fs->super->s_uuid)); + crc = ext2fs_crc16(crc, &group, sizeof(group)); + crc = ext2fs_crc16(crc, desc, offset); + offset += sizeof(desc->bg_checksum); /* skip checksum */ + /* for checksum of struct ext4_group_desc do the rest...*/ + if (offset < size) { + crc = ext2fs_crc16(crc, (char *)desc + offset, + size - offset); + } + +out: return crc; } int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) { - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && + if (ext2fs_has_group_desc_csum(fs) && (ext2fs_bg_checksum(fs, group) != ext2fs_group_desc_csum(fs, group))) return 0; @@ -738,8 +755,7 @@ int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group) { - if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + if (!ext2fs_has_group_desc_csum(fs)) return; /* ext2fs_bg_checksum_set() sets the actual checksum field but @@ -773,8 +789,7 @@ errcode_t ext2fs_set_gdt_csum(ext2_filsys fs) if (!fs->inode_map) return EXT2_ET_NO_INODE_BITMAP; - if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + if (!ext2fs_has_group_desc_csum(fs)) return 0; for (i = 0; i < fs->group_desc_count; i++) { diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 9574525..eeac04d 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -642,6 +642,12 @@ typedef struct stat ext2fs_struct_stat; /* * function prototypes */ +static inline int ext2fs_has_group_desc_csum(ext2_filsys fs) +{ + return EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM | + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); +} /* alloc.c */ extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode, diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index a63ea18..a22cab4 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -435,8 +435,7 @@ ipg_retry: * bitmaps will be accounted for when allocated). */ free_blocks = 0; - csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM); + csum_flag = ext2fs_has_group_desc_csum(fs); for (i = 0; i < fs->group_desc_count; i++) { /* * Don't set the BLOCK_UNINIT group for the last group diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index 74703c5..3e6d853 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -157,8 +157,7 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, scan->current_group); scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); scan->blocks_left = scan->fs->inode_blocks_per_group; - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { + if (ext2fs_has_group_desc_csum(fs)) { scan->inodes_left -= ext2fs_bg_itable_unused(fs, scan->current_group); scan->blocks_left = @@ -183,8 +182,7 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, } if (scan->fs->badblocks && scan->fs->badblocks->num) scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + if (ext2fs_has_group_desc_csum(fs)) scan->scan_flags |= EXT2_SF_DO_LAZY; *ret_scan = scan; return 0; @@ -250,8 +248,7 @@ static errcode_t get_next_blockgroup(ext2_inode_scan scan) scan->bytes_left = 0; scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super); scan->blocks_left = fs->inode_blocks_per_group; - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { + if (ext2fs_has_group_desc_csum(fs)) { scan->inodes_left -= ext2fs_bg_itable_unused(fs, scan->current_group); scan->blocks_left = diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index d2b64f4..2dc9b94 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -382,8 +382,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, * If recovery is from backup superblock, Clear _UNININT flags & * reset bg_itable_unused to zero */ - if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { + if (superblock > 1 && ext2fs_has_group_desc_csum(fs)) { dgrp_t group; for (group = 0; group < fs->group_desc_count; group++) { diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index a5097c1..18e18aa 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -36,7 +36,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) unsigned int nbits; errcode_t retval; char *block_buf = NULL, *inode_buf = NULL; - int csum_flag = 0; + int csum_flag; blk64_t blk; blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); ext2_ino_t ino_itr = 1; @@ -46,9 +46,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) if (!(fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) - csum_flag = 1; + csum_flag = ext2fs_has_group_desc_csum(fs); inode_nbytes = block_nbytes = 0; if (do_block) { @@ -168,7 +166,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) errcode_t retval; int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; - int csum_flag = 0; + int csum_flag; int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE; unsigned int cnt; blk64_t blk; @@ -181,9 +179,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) fs->write_bitmaps = ext2fs_write_bitmaps; - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) - csum_flag = 1; + csum_flag = ext2fs_has_group_desc_csum(fs); retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); if (retval) diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index 23dec30..40398a7 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -114,7 +114,7 @@ static void print_bg_opts(ext2_filsys fs, dgrp_t i) { int first = 1, bg_flags = 0; - if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) + if (ext2fs_has_group_desc_csum(fs)) bg_flags = ext2fs_bg_flags(fs, i); print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "INODE_UNINIT", @@ -190,7 +190,7 @@ static void list_desc (ext2_filsys fs) print_range(first_block, last_block); fputs(")", stdout); print_bg_opts(fs, i); - if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) + if (ext2fs_has_group_desc_csum(fs)) printf(_(" Checksum 0x%04x, unused inodes %u\n"), ext2fs_bg_checksum(fs, i), ext2fs_bg_itable_unused(fs, i)); diff --git a/resize/resize2fs.c b/resize/resize2fs.c index dc2805d..8a02ff4 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -191,8 +191,7 @@ static void fix_uninit_block_bitmaps(ext2_filsys fs) int old_desc_blocks; dgrp_t g; - if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) + if (!ext2fs_has_group_desc_csum(fs)) return; for (g=0; g < fs->group_desc_count; g++) { @@ -482,8 +481,7 @@ retry: group_block = fs->super->s_first_data_block + old_fs->group_desc_count * fs->super->s_blocks_per_group; - csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM); + csum_flag = ext2fs_has_group_desc_csum(fs); adj = old_fs->group_desc_count; max_group = fs->group_desc_count - adj; if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) @@ -743,8 +741,7 @@ static void mark_fs_metablock(ext2_resize_t rfs, } else if (IS_INODE_TB(fs, group, blk)) { ext2fs_inode_table_loc_set(fs, group, 0); rfs->needed_blocks++; - } else if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && + } else if (ext2fs_has_group_desc_csum(fs) && (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) { /* * If the block bitmap is uninitialized, which means @@ -804,8 +801,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs) for (blk = ext2fs_blocks_count(fs->super); blk < ext2fs_blocks_count(old_fs->super); blk++) { g = ext2fs_group_of_blk2(fs, blk); - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && + if (ext2fs_has_group_desc_csum(fs) && ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) { /* * The block bitmap is uninitialized, so skip -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html