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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABCAAGBQJQLlVSAAoJENNvdpvBGATwhOYQAKx22YF9+SHnnVv2GtCQrsE6 N3acE/FoDYiO1/LRa5M6NDO3ZIL4Vqi6409LYFQky/SQL8ziM5CBeLOBD9qPTE1L AGrzWn4vzZcjEf90ZEBN99fS5Uj1A9Axz2denxy7Hfb2HcSXfcuuVQXpdS42cFo8 gwtlX4jxmPkbjRlAdeqYVBNuWpTZ0a+UyLc4A6v3aLcbzPSJvPYmI7mKCksiSySU yt0atjMDb56blAQJ2TITdAZN6rQShNzyok2pPfxaLusl5g0Gtjq8sSEPof1PQ1zq gDFc+kpZvUyPdwQzV3IL8+TodFFZ0x/2OhqoYCTKajROLHGjQFsdkb8EJbnNeDff EDxIjeVJR0kzSuSNWu+n5028lmEd9Sk7Ykr37cHeUxG8/0SADUqSDQYNhvbOPQsj iq5dwF79tKjuMqjJrABuWA1ZNgHBISXgyBmHLXgEk3LrgucT9UIg8Zlkhq480SYO JXhmkO2Ka4UwkVUShoWgRtEzRgUxhINBShs6g67zwm6slS4s2CWHnqhUn6EQe6+r DY/hoUA8KbdG3Cf5iJBFM2kUO68CDIXeJjocA7JvlouRgQSxmkOceIuk7DusAitM nHJKAtSNgC/z7yMoNi7YN0S5YYcCebmO1MEPzYSpPH07YwLJVNmh9Fk6BIfb7vi3 vJSQMBrgGrbaXrnhBA7z =Zulv -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
ef824bfba2
|
@ -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,
|
||||
struct ext4_group_desc *desc,
|
||||
unsigned int block_group,
|
||||
struct buffer_head *bh)
|
||||
/*
|
||||
* 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,14 +336,26 @@ 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))
|
||||
set_buffer_verified(bh);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -2662,6 +2662,7 @@ cont:
|
|||
}
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1125,6 +1125,7 @@ extern int jbd2_journal_destroy (journal_t *);
|
|||
extern int jbd2_journal_recover (journal_t *journal);
|
||||
extern int jbd2_journal_wipe (journal_t *, int);
|
||||
extern int jbd2_journal_skip_recovery (journal_t *);
|
||||
extern void jbd2_journal_update_sb_errno(journal_t *);
|
||||
extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t,
|
||||
unsigned long, int);
|
||||
extern void __jbd2_journal_abort_hard (journal_t *);
|
||||
|
|
Loading…
Reference in New Issue