mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
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;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_valid_block_bitmap(struct super_block *sb,
|
/*
|
||||||
struct ext4_group_desc *desc,
|
* Return the block number which was discovered to be invalid, or 0 if
|
||||||
unsigned int block_group,
|
* the block bitmap is valid.
|
||||||
struct buffer_head *bh)
|
*/
|
||||||
|
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 offset;
|
||||||
ext4_grpblk_t next_zero_bit;
|
ext4_grpblk_t next_zero_bit;
|
||||||
ext4_fsblk_t bitmap_blk;
|
ext4_fsblk_t blk;
|
||||||
ext4_fsblk_t group_first_block;
|
ext4_fsblk_t group_first_block;
|
||||||
|
|
||||||
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
|
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
|
* or it has to also read the block group where the bitmaps
|
||||||
* are located to verify they are set.
|
* are located to verify they are set.
|
||||||
*/
|
*/
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
group_first_block = ext4_group_first_block_no(sb, block_group);
|
group_first_block = ext4_group_first_block_no(sb, block_group);
|
||||||
|
|
||||||
/* check whether block bitmap block number is set */
|
/* check whether block bitmap block number is set */
|
||||||
bitmap_blk = ext4_block_bitmap(sb, desc);
|
blk = ext4_block_bitmap(sb, desc);
|
||||||
offset = bitmap_blk - group_first_block;
|
offset = blk - group_first_block;
|
||||||
if (!ext4_test_bit(offset, bh->b_data))
|
if (!ext4_test_bit(offset, bh->b_data))
|
||||||
/* bad block bitmap */
|
/* bad block bitmap */
|
||||||
goto err_out;
|
return blk;
|
||||||
|
|
||||||
/* check whether the inode bitmap block number is set */
|
/* check whether the inode bitmap block number is set */
|
||||||
bitmap_blk = ext4_inode_bitmap(sb, desc);
|
blk = ext4_inode_bitmap(sb, desc);
|
||||||
offset = bitmap_blk - group_first_block;
|
offset = blk - group_first_block;
|
||||||
if (!ext4_test_bit(offset, bh->b_data))
|
if (!ext4_test_bit(offset, bh->b_data))
|
||||||
/* bad block bitmap */
|
/* bad block bitmap */
|
||||||
goto err_out;
|
return blk;
|
||||||
|
|
||||||
/* check whether the inode table block number is set */
|
/* check whether the inode table block number is set */
|
||||||
bitmap_blk = ext4_inode_table(sb, desc);
|
blk = ext4_inode_table(sb, desc);
|
||||||
offset = bitmap_blk - group_first_block;
|
offset = blk - group_first_block;
|
||||||
next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
|
next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
|
||||||
offset + EXT4_SB(sb)->s_itb_per_group,
|
offset + EXT4_SB(sb)->s_itb_per_group,
|
||||||
offset);
|
offset);
|
||||||
if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group)
|
if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group)
|
||||||
/* good bitmap for inode tables */
|
/* bad bitmap for inode tables */
|
||||||
return 1;
|
return blk;
|
||||||
|
|
||||||
err_out:
|
|
||||||
ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
|
|
||||||
block_group, bitmap_blk);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,14 +336,26 @@ void ext4_validate_block_bitmap(struct super_block *sb,
|
|||||||
unsigned int block_group,
|
unsigned int block_group,
|
||||||
struct buffer_head *bh)
|
struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
|
ext4_fsblk_t blk;
|
||||||
|
|
||||||
if (buffer_verified(bh))
|
if (buffer_verified(bh))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ext4_lock_group(sb, block_group);
|
ext4_lock_group(sb, block_group);
|
||||||
if (ext4_valid_block_bitmap(sb, desc, block_group, bh) &&
|
blk = ext4_valid_block_bitmap(sb, desc, block_group, bh);
|
||||||
ext4_block_bitmap_csum_verify(sb, block_group, desc, bh,
|
if (unlikely(blk != 0)) {
|
||||||
EXT4_BLOCKS_PER_GROUP(sb) / 8))
|
ext4_unlock_group(sb, block_group);
|
||||||
set_buffer_verified(bh);
|
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);
|
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)
|
if (provided == calculated)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2662,6 +2662,7 @@ cont:
|
|||||||
}
|
}
|
||||||
path[0].p_depth = depth;
|
path[0].p_depth = depth;
|
||||||
path[0].p_hdr = ext_inode_hdr(inode);
|
path[0].p_hdr = ext_inode_hdr(inode);
|
||||||
|
i = 0;
|
||||||
|
|
||||||
if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
|
if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
|
@ -948,6 +948,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
|||||||
ei->i_reserved_meta_blocks = 0;
|
ei->i_reserved_meta_blocks = 0;
|
||||||
ei->i_allocated_meta_blocks = 0;
|
ei->i_allocated_meta_blocks = 0;
|
||||||
ei->i_da_metadata_calc_len = 0;
|
ei->i_da_metadata_calc_len = 0;
|
||||||
|
ei->i_da_metadata_calc_last_lblock = 0;
|
||||||
spin_lock_init(&(ei->i_block_reservation_lock));
|
spin_lock_init(&(ei->i_block_reservation_lock));
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
ei->i_reserved_quota = 0;
|
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);
|
ext4_group_t i, ngroups = ext4_get_groups_count(sb);
|
||||||
int s, j, count = 0;
|
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) +
|
first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
|
||||||
(grp * EXT4_BLOCKS_PER_GROUP(sb));
|
(grp * EXT4_BLOCKS_PER_GROUP(sb));
|
||||||
last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;
|
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);
|
ext4_commit_super(sb, 1);
|
||||||
|
|
||||||
jbd2_journal_clear_err(journal);
|
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
|
* Update a journal's errno. Write updated superblock to disk waiting for IO
|
||||||
* to complete.
|
* 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;
|
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);
|
jbd2_write_superblock(journal, WRITE_SYNC);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the superblock for a given journal, performing initial
|
* 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_recover (journal_t *journal);
|
||||||
extern int jbd2_journal_wipe (journal_t *, int);
|
extern int jbd2_journal_wipe (journal_t *, int);
|
||||||
extern int jbd2_journal_skip_recovery (journal_t *);
|
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,
|
extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t,
|
||||||
unsigned long, int);
|
unsigned long, int);
|
||||||
extern void __jbd2_journal_abort_hard (journal_t *);
|
extern void __jbd2_journal_abort_hard (journal_t *);
|
||||||
|
Loading…
Reference in New Issue
Block a user