| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Mon, 19 Feb 2018 14:16:47 -0500 |
| Subject: ext4: don't update checksum of new initialized bitmaps |
| |
| commit 044e6e3d74a3d7103a0c8a9305dfd94d64000660 upstream. |
| |
| When reading the inode or block allocation bitmap, if the bitmap needs |
| to be initialized, do not update the checksum in the block group |
| descriptor. That's because we're not set up to journal those changes. |
| Instead, just set the verified bit on the bitmap block, so that it's |
| not necessary to validate the checksum. |
| |
| When a block or inode allocation actually happens, at that point the |
| checksum will be calculated, and update of the bg descriptor block |
| will be properly journalled. |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| [bwh: Backported to 3.16: |
| - Deleted code is slightly different |
| - Adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/ext4/balloc.c | 3 +-- |
| fs/ext4/ialloc.c | 47 +++-------------------------------------------- |
| 2 files changed, 4 insertions(+), 46 deletions(-) |
| |
| --- a/fs/ext4/balloc.c |
| +++ b/fs/ext4/balloc.c |
| @@ -239,8 +239,6 @@ static int ext4_init_block_bitmap(struct |
| */ |
| ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), |
| sb->s_blocksize * 8, bh->b_data); |
| - ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); |
| - ext4_group_desc_csum_set(sb, block_group, gdp); |
| return 0; |
| } |
| |
| @@ -464,6 +462,7 @@ ext4_read_block_bitmap_nowait(struct sup |
| err = ext4_init_block_bitmap(sb, bh, block_group, desc); |
| set_bitmap_uptodate(bh); |
| set_buffer_uptodate(bh); |
| + set_buffer_verified(bh); |
| ext4_unlock_group(sb, block_group); |
| unlock_buffer(bh); |
| if (err) |
| --- a/fs/ext4/ialloc.c |
| +++ b/fs/ext4/ialloc.c |
| @@ -64,45 +64,6 @@ void ext4_mark_bitmap_end(int start_bit, |
| memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3); |
| } |
| |
| -/* Initializes an uninitialized inode bitmap */ |
| -static unsigned ext4_init_inode_bitmap(struct super_block *sb, |
| - struct buffer_head *bh, |
| - ext4_group_t block_group, |
| - struct ext4_group_desc *gdp) |
| -{ |
| - struct ext4_group_info *grp; |
| - struct ext4_sb_info *sbi = EXT4_SB(sb); |
| - J_ASSERT_BH(bh, buffer_locked(bh)); |
| - |
| - /* If checksum is bad mark all blocks and inodes use to prevent |
| - * allocation, essentially implementing a per-group read-only flag. */ |
| - if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { |
| - ext4_error(sb, "Checksum bad for group %u", block_group); |
| - grp = ext4_get_group_info(sb, block_group); |
| - if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) |
| - percpu_counter_sub(&sbi->s_freeclusters_counter, |
| - grp->bb_free); |
| - set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); |
| - if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { |
| - int count; |
| - count = ext4_free_inodes_count(sb, gdp); |
| - percpu_counter_sub(&sbi->s_freeinodes_counter, |
| - count); |
| - } |
| - set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); |
| - return 0; |
| - } |
| - |
| - memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); |
| - ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, |
| - bh->b_data); |
| - ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh, |
| - EXT4_INODES_PER_GROUP(sb) / 8); |
| - ext4_group_desc_csum_set(sb, block_group, gdp); |
| - |
| - return EXT4_INODES_PER_GROUP(sb); |
| -} |
| - |
| void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate) |
| { |
| if (uptodate) { |
| @@ -166,7 +127,9 @@ ext4_read_inode_bitmap(struct super_bloc |
| put_bh(bh); |
| return NULL; |
| } |
| - ext4_init_inode_bitmap(sb, bh, block_group, desc); |
| + memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); |
| + ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), |
| + sb->s_blocksize * 8, bh->b_data); |
| set_bitmap_uptodate(bh); |
| set_buffer_uptodate(bh); |
| set_buffer_verified(bh); |