[Bionic] UBUNTU: SAUCE: Revert "ext4: don't update checksum of new initialized bitmaps"

Message ID 1530812193-14763-1-git-send-email-kamal@canonical.com
State New
Headers show
Series
  • [Bionic] UBUNTU: SAUCE: Revert "ext4: don't update checksum of new initialized bitmaps"
Related show

Commit Message

Kamal Mostafa July 5, 2018, 5:36 p.m.
BugLink: https://bugs.launchpad.net/bugs/1780137

This reverts commit 555bc9b1421f10d94a1192c7eea4a59faca3e711.

This stable patch (555bc9b ext4: don't update checksum of new
initialized bitmaps) was identified as the cause of

https://bugs.launchpad.net/bugs/1780137
[Regression] EXT4-fs error (device sda1): ext4_validate_inode_bitmap:99:
    comm stress-ng: Corrupt inode bitmap

Mainline also exhibits the problem.

Cc: dann frazier <dann.frazier@canonical.com>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
---
 fs/ext4/balloc.c |  3 ++-
 fs/ext4/ialloc.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 46 insertions(+), 4 deletions(-)

Comments

Kamal Mostafa July 10, 2018, 9:12 p.m. | #1
NAK this Revert; a better fix is in development upstream, as noted in
the LP bug.

 -Kamal

On Thu, Jul 05, 2018 at 10:36:33AM -0700, Kamal Mostafa wrote:
> BugLink: https://bugs.launchpad.net/bugs/1780137
> 
> This reverts commit 555bc9b1421f10d94a1192c7eea4a59faca3e711.
> 
> This stable patch (555bc9b ext4: don't update checksum of new
> initialized bitmaps) was identified as the cause of
> 
> https://bugs.launchpad.net/bugs/1780137
> [Regression] EXT4-fs error (device sda1): ext4_validate_inode_bitmap:99:
>     comm stress-ng: Corrupt inode bitmap
> 
> Mainline also exhibits the problem.
> 
> Cc: dann frazier <dann.frazier@canonical.com>
> Signed-off-by: Kamal Mostafa <kamal@canonical.com>
> ---
>  fs/ext4/balloc.c |  3 ++-
>  fs/ext4/ialloc.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 46 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
> index 824c99e..607c08f 100644
> --- a/fs/ext4/balloc.c
> +++ b/fs/ext4/balloc.c
> @@ -243,6 +243,8 @@ static int ext4_init_block_bitmap(struct super_block *sb,
>  	 */
>  	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;
>  }
>  
> @@ -446,7 +448,6 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
>  		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) {
> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
> index 8bd0759..1e76c08 100644
> --- a/fs/ext4/ialloc.c
> +++ b/fs/ext4/ialloc.c
> @@ -66,6 +66,44 @@ void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
>  		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
>  }
>  
> +/* Initializes an uninitialized inode bitmap */
> +static int 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)) {
> +		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 -EFSBADCRC;
> +	}
> +
> +	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 0;
> +}
> +
>  void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate)
>  {
>  	if (uptodate) {
> @@ -149,14 +187,17 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
>  
>  	ext4_lock_group(sb, block_group);
>  	if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
> -		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);
> +		err = ext4_init_inode_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) {
> +			ext4_error(sb, "Failed to init inode bitmap for group "
> +				   "%u: %d", block_group, err);
> +			goto out;
> +		}
>  		return bh;
>  	}
>  	ext4_unlock_group(sb, block_group);
> -- 
> 2.7.4
>

Patch

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 824c99e..607c08f 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -243,6 +243,8 @@  static int ext4_init_block_bitmap(struct super_block *sb,
 	 */
 	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;
 }
 
@@ -446,7 +448,6 @@  ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
 		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) {
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 8bd0759..1e76c08 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -66,6 +66,44 @@  void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
 		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
 }
 
+/* Initializes an uninitialized inode bitmap */
+static int 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)) {
+		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 -EFSBADCRC;
+	}
+
+	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 0;
+}
+
 void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate)
 {
 	if (uptodate) {
@@ -149,14 +187,17 @@  ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
 
 	ext4_lock_group(sb, block_group);
 	if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
-		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);
+		err = ext4_init_inode_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) {
+			ext4_error(sb, "Failed to init inode bitmap for group "
+				   "%u: %d", block_group, err);
+			goto out;
+		}
 		return bh;
 	}
 	ext4_unlock_group(sb, block_group);