Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef824bfb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 bug fixes from Ted Ts'o:
 "The following are all bug fixes and regressions.  The most notable are
  the ones which cause problems for ext4 on RAID --- a performance
  problem when mounting very large filesystems, and a kernel OOPS when
  doing an rm -rf on large directory hierarchies on fast devices."

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: fix kernel BUG on large-scale rm -rf commands
  ext4: fix long mount times on very big file systems
  ext4: don't call ext4_error while block group is locked
  ext4: avoid kmemcheck complaint from reading uninitialized memory
  ext4: make sure the journal sb is written in ext4_clear_journal_err()
parents d807ff83 89a4e48f
Loading
Loading
Loading
Loading
+37 −25
Original line number Diff line number Diff line
@@ -280,14 +280,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
	return desc;
}

static int ext4_valid_block_bitmap(struct super_block *sb,
/*
 * Return the block number which was discovered to be invalid, or 0 if
 * the block bitmap is valid.
 */
static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
					    struct ext4_group_desc *desc,
					    unsigned int block_group,
					    struct buffer_head *bh)
{
	ext4_grpblk_t offset;
	ext4_grpblk_t next_zero_bit;
	ext4_fsblk_t bitmap_blk;
	ext4_fsblk_t blk;
	ext4_fsblk_t group_first_block;

	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
@@ -297,37 +301,33 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
		 * or it has to also read the block group where the bitmaps
		 * are located to verify they are set.
		 */
		return 1;
		return 0;
	}
	group_first_block = ext4_group_first_block_no(sb, block_group);

	/* check whether block bitmap block number is set */
	bitmap_blk = ext4_block_bitmap(sb, desc);
	offset = bitmap_blk - group_first_block;
	blk = ext4_block_bitmap(sb, desc);
	offset = blk - group_first_block;
	if (!ext4_test_bit(offset, bh->b_data))
		/* bad block bitmap */
		goto err_out;
		return blk;

	/* check whether the inode bitmap block number is set */
	bitmap_blk = ext4_inode_bitmap(sb, desc);
	offset = bitmap_blk - group_first_block;
	blk = ext4_inode_bitmap(sb, desc);
	offset = blk - group_first_block;
	if (!ext4_test_bit(offset, bh->b_data))
		/* bad block bitmap */
		goto err_out;
		return blk;

	/* check whether the inode table block number is set */
	bitmap_blk = ext4_inode_table(sb, desc);
	offset = bitmap_blk - group_first_block;
	blk = ext4_inode_table(sb, desc);
	offset = blk - group_first_block;
	next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
				offset + EXT4_SB(sb)->s_itb_per_group,
				offset);
	if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group)
		/* good bitmap for inode tables */
		return 1;

err_out:
	ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
			block_group, bitmap_blk);
	if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group)
		/* bad bitmap for inode tables */
		return blk;
	return 0;
}

@@ -336,13 +336,25 @@ void ext4_validate_block_bitmap(struct super_block *sb,
			       unsigned int block_group,
			       struct buffer_head *bh)
{
	ext4_fsblk_t	blk;

	if (buffer_verified(bh))
		return;

	ext4_lock_group(sb, block_group);
	if (ext4_valid_block_bitmap(sb, desc, block_group, bh) &&
	    ext4_block_bitmap_csum_verify(sb, block_group, desc, bh,
					  EXT4_BLOCKS_PER_GROUP(sb) / 8))
	blk = ext4_valid_block_bitmap(sb, desc, block_group, bh);
	if (unlikely(blk != 0)) {
		ext4_unlock_group(sb, block_group);
		ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
			   block_group, blk);
		return;
	}
	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
			desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
		ext4_unlock_group(sb, block_group);
		ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
		return;
	}
	set_buffer_verified(bh);
	ext4_unlock_group(sb, block_group);
}
+0 −1
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
	if (provided == calculated)
		return 1;

	ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group);
	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -2662,6 +2662,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
		}
		path[0].p_depth = depth;
		path[0].p_hdr = ext_inode_hdr(inode);
		i = 0;

		if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
			err = -EIO;
+6 −0
Original line number Diff line number Diff line
@@ -948,6 +948,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
	ei->i_reserved_meta_blocks = 0;
	ei->i_allocated_meta_blocks = 0;
	ei->i_da_metadata_calc_len = 0;
	ei->i_da_metadata_calc_last_lblock = 0;
	spin_lock_init(&(ei->i_block_reservation_lock));
#ifdef CONFIG_QUOTA
	ei->i_reserved_quota = 0;
@@ -3108,6 +3109,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
	ext4_group_t		i, ngroups = ext4_get_groups_count(sb);
	int			s, j, count = 0;

	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC))
		return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
			sbi->s_itb_per_group + 2);

	first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
		(grp * EXT4_BLOCKS_PER_GROUP(sb));
	last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;
@@ -4419,6 +4424,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
		ext4_commit_super(sb, 1);

		jbd2_journal_clear_err(journal);
		jbd2_journal_update_sb_errno(journal);
	}
}

+2 −1
Original line number Diff line number Diff line
@@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal)
 * Update a journal's errno.  Write updated superblock to disk waiting for IO
 * to complete.
 */
static void jbd2_journal_update_sb_errno(journal_t *journal)
void jbd2_journal_update_sb_errno(journal_t *journal)
{
	journal_superblock_t *sb = journal->j_superblock;

@@ -1390,6 +1390,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)

	jbd2_write_superblock(journal, WRITE_SYNC);
}
EXPORT_SYMBOL(jbd2_journal_update_sb_errno);

/*
 * Read the superblock for a given journal, performing initial
Loading