More bug fixes for ext4 -- most importantly, a fix for a bug
(introduced in 3.15) that can end up triggering a file system corruption error after a journal replay. (It shouldn't lead to any actual data corruption, but it is scary and can force file systems to be remounted read-only, etc.) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJTwuY+AAoJENNvdpvBGATwgN8QAJ2/S5GFxQwHbglHmayXYuMQ fU411FwJ1wbqjYyYb+jyBoYcsgpsCKPTqA2JbPlHsFTm2Ec+BPzsybhtYw5ybdeW 1qAfPTSgNxYXroNwpaqOamxgfXgOaV4iqwvZ4tYcLcrtPq0MOcC5rlSaKMdJuSA1 6M2/8PijOTndUVJpS/GhSMdKlTAXjtfv9V6t/pfLuoo7cNadlggpJnwC8Qm9DNAA 5ETVZK44q2+2YvGwrvY6LBb9BVBpL29YbWPNqqw/OXXY++ZFhBJV07osZO38MpsB QzUyfRaMTgm9/BdbkG8uxA7Zk6C0YBl5eC4aU79LWGWjGO225CLj95LoBOVjQw9f eh+RFGapwVvtyzScDF/a9pH6UwGco/s4kCq8rLr2ztljlO595N3LUwhQBHtiSGtm fr65NRDyJMXbqy8yLGrlOnP/4ll2VfTH+el2+tzr5smoTD29EASM155hKDDUOAG0 TrDHtNrxG1MIROHjp+HSui424Op7NXTnfjwmuKzo+mGpPOcPclPSmAacFJpRGVBE 220hnk+LrBf525nJzQYHifdCL+JAqbWv/S4YSRGizgppK3DlO/gYcu1zpWb0WWuo 0VuvxUZDSIZY1aVpMEOQov74WtovB7YyG8RPHl7h2m5dJuLLFgJmLDMDTJR1LLNT +tHNJ6jERLQz9wqTvquh =OX7Z -----END PGP SIGNATURE----- Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 bugfixes from Ted Ts'o: "More bug fixes for ext4 -- most importantly, a fix for a bug introduced in 3.15 that can end up triggering a file system corruption error after a journal replay. It shouldn't lead to any actual data corruption, but it is scary and can force file systems to be remounted read-only, etc" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: fix potential null pointer dereference in ext4_free_inode ext4: fix a potential deadlock in __ext4_es_shrink() ext4: revert commit which was causing fs corruption after journal replays ext4: disable synchronous transaction batching if max_batch_time==0 ext4: clarify ext4_error message in ext4_mb_generate_buddy_error() ext4: clarify error count warning messages ext4: fix unjournalled bg descriptor while initializing inode bitmap
This commit is contained in:
commit
18b34d9a7a
5 changed files with 44 additions and 45 deletions
|
@ -966,10 +966,10 @@ retry:
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ei->i_es_lru_nr == 0 || ei == locked_ei)
|
||||
if (ei->i_es_lru_nr == 0 || ei == locked_ei ||
|
||||
!write_trylock(&ei->i_es_lock))
|
||||
continue;
|
||||
|
||||
write_lock(&ei->i_es_lock);
|
||||
shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
|
||||
if (ei->i_es_lru_nr == 0)
|
||||
list_del_init(&ei->i_es_lru);
|
||||
|
|
|
@ -338,7 +338,7 @@ out:
|
|||
fatal = err;
|
||||
} else {
|
||||
ext4_error(sb, "bit already cleared for inode %lu", ino);
|
||||
if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
|
||||
if (gdp && !EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
|
||||
int count;
|
||||
count = ext4_free_inodes_count(sb, gdp);
|
||||
percpu_counter_sub(&sbi->s_freeinodes_counter,
|
||||
|
@ -874,6 +874,13 @@ got:
|
|||
goto out;
|
||||
}
|
||||
|
||||
BUFFER_TRACE(group_desc_bh, "get_write_access");
|
||||
err = ext4_journal_get_write_access(handle, group_desc_bh);
|
||||
if (err) {
|
||||
ext4_std_error(sb, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We may have to initialize the block bitmap if it isn't already */
|
||||
if (ext4_has_group_desc_csum(sb) &&
|
||||
gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
|
||||
|
@ -910,13 +917,6 @@ got:
|
|||
}
|
||||
}
|
||||
|
||||
BUFFER_TRACE(group_desc_bh, "get_write_access");
|
||||
err = ext4_journal_get_write_access(handle, group_desc_bh);
|
||||
if (err) {
|
||||
ext4_std_error(sb, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Update the relevant bg descriptor fields */
|
||||
if (ext4_has_group_desc_csum(sb)) {
|
||||
int free;
|
||||
|
|
|
@ -752,8 +752,8 @@ void ext4_mb_generate_buddy(struct super_block *sb,
|
|||
|
||||
if (free != grp->bb_free) {
|
||||
ext4_grp_locked_error(sb, group, 0, 0,
|
||||
"%u clusters in bitmap, %u in gd; "
|
||||
"block bitmap corrupt.",
|
||||
"block bitmap and bg descriptor "
|
||||
"inconsistent: %u vs %u free clusters",
|
||||
free, grp->bb_free);
|
||||
/*
|
||||
* If we intend to continue, we consider group descriptor
|
||||
|
|
|
@ -1525,8 +1525,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
|
|||
arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
|
||||
sbi->s_commit_interval = HZ * arg;
|
||||
} else if (token == Opt_max_batch_time) {
|
||||
if (arg == 0)
|
||||
arg = EXT4_DEF_MAX_BATCH_TIME;
|
||||
sbi->s_max_batch_time = arg;
|
||||
} else if (token == Opt_min_batch_time) {
|
||||
sbi->s_min_batch_time = arg;
|
||||
|
@ -2809,10 +2807,11 @@ static void print_daily_error_info(unsigned long arg)
|
|||
es = sbi->s_es;
|
||||
|
||||
if (es->s_error_count)
|
||||
ext4_msg(sb, KERN_NOTICE, "error count: %u",
|
||||
/* fsck newer than v1.41.13 is needed to clean this condition. */
|
||||
ext4_msg(sb, KERN_NOTICE, "error count since last fsck: %u",
|
||||
le32_to_cpu(es->s_error_count));
|
||||
if (es->s_first_error_time) {
|
||||
printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d",
|
||||
printk(KERN_NOTICE "EXT4-fs (%s): initial error at time %u: %.*s:%d",
|
||||
sb->s_id, le32_to_cpu(es->s_first_error_time),
|
||||
(int) sizeof(es->s_first_error_func),
|
||||
es->s_first_error_func,
|
||||
|
@ -2826,7 +2825,7 @@ static void print_daily_error_info(unsigned long arg)
|
|||
printk("\n");
|
||||
}
|
||||
if (es->s_last_error_time) {
|
||||
printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d",
|
||||
printk(KERN_NOTICE "EXT4-fs (%s): last error at time %u: %.*s:%d",
|
||||
sb->s_id, le32_to_cpu(es->s_last_error_time),
|
||||
(int) sizeof(es->s_last_error_func),
|
||||
es->s_last_error_func,
|
||||
|
@ -3880,38 +3879,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
goto failed_mount2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* set up enough so that it can read an inode,
|
||||
* and create new inode for buddy allocator
|
||||
*/
|
||||
sbi->s_gdb_count = db_count;
|
||||
if (!test_opt(sb, NOLOAD) &&
|
||||
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
|
||||
sb->s_op = &ext4_sops;
|
||||
else
|
||||
sb->s_op = &ext4_nojournal_sops;
|
||||
|
||||
ext4_ext_init(sb);
|
||||
err = ext4_mb_init(sb);
|
||||
if (err) {
|
||||
ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
|
||||
err);
|
||||
goto failed_mount2;
|
||||
}
|
||||
|
||||
if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
|
||||
ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
|
||||
goto failed_mount2a;
|
||||
goto failed_mount2;
|
||||
}
|
||||
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
||||
if (!ext4_fill_flex_info(sb)) {
|
||||
ext4_msg(sb, KERN_ERR,
|
||||
"unable to initialize "
|
||||
"flex_bg meta info!");
|
||||
goto failed_mount2a;
|
||||
goto failed_mount2;
|
||||
}
|
||||
|
||||
sbi->s_gdb_count = db_count;
|
||||
get_random_bytes(&sbi->s_next_generation, sizeof(u32));
|
||||
spin_lock_init(&sbi->s_next_gen_lock);
|
||||
|
||||
|
@ -3946,6 +3926,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
sbi->s_stripe = ext4_get_stripe_size(sbi);
|
||||
sbi->s_extent_max_zeroout_kb = 32;
|
||||
|
||||
/*
|
||||
* set up enough so that it can read an inode
|
||||
*/
|
||||
if (!test_opt(sb, NOLOAD) &&
|
||||
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
|
||||
sb->s_op = &ext4_sops;
|
||||
else
|
||||
sb->s_op = &ext4_nojournal_sops;
|
||||
sb->s_export_op = &ext4_export_ops;
|
||||
sb->s_xattr = ext4_xattr_handlers;
|
||||
#ifdef CONFIG_QUOTA
|
||||
|
@ -4135,13 +4123,21 @@ no_journal:
|
|||
if (err) {
|
||||
ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
|
||||
"reserved pool", ext4_calculate_resv_clusters(sb));
|
||||
goto failed_mount5;
|
||||
goto failed_mount4a;
|
||||
}
|
||||
|
||||
err = ext4_setup_system_zone(sb);
|
||||
if (err) {
|
||||
ext4_msg(sb, KERN_ERR, "failed to initialize system "
|
||||
"zone (%d)", err);
|
||||
goto failed_mount4a;
|
||||
}
|
||||
|
||||
ext4_ext_init(sb);
|
||||
err = ext4_mb_init(sb);
|
||||
if (err) {
|
||||
ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
|
||||
err);
|
||||
goto failed_mount5;
|
||||
}
|
||||
|
||||
|
@ -4218,8 +4214,11 @@ failed_mount8:
|
|||
failed_mount7:
|
||||
ext4_unregister_li_request(sb);
|
||||
failed_mount6:
|
||||
ext4_release_system_zone(sb);
|
||||
ext4_mb_release(sb);
|
||||
failed_mount5:
|
||||
ext4_ext_release(sb);
|
||||
ext4_release_system_zone(sb);
|
||||
failed_mount4a:
|
||||
dput(sb->s_root);
|
||||
sb->s_root = NULL;
|
||||
failed_mount4:
|
||||
|
@ -4243,14 +4242,11 @@ failed_mount3:
|
|||
percpu_counter_destroy(&sbi->s_extent_cache_cnt);
|
||||
if (sbi->s_mmp_tsk)
|
||||
kthread_stop(sbi->s_mmp_tsk);
|
||||
failed_mount2a:
|
||||
ext4_mb_release(sb);
|
||||
failed_mount2:
|
||||
for (i = 0; i < db_count; i++)
|
||||
brelse(sbi->s_group_desc[i]);
|
||||
ext4_kvfree(sbi->s_group_desc);
|
||||
failed_mount:
|
||||
ext4_ext_release(sb);
|
||||
if (sbi->s_chksum_driver)
|
||||
crypto_free_shash(sbi->s_chksum_driver);
|
||||
if (sbi->s_proc) {
|
||||
|
|
|
@ -1588,9 +1588,12 @@ int jbd2_journal_stop(handle_t *handle)
|
|||
* to perform a synchronous write. We do this to detect the
|
||||
* case where a single process is doing a stream of sync
|
||||
* writes. No point in waiting for joiners in that case.
|
||||
*
|
||||
* Setting max_batch_time to 0 disables this completely.
|
||||
*/
|
||||
pid = current->pid;
|
||||
if (handle->h_sync && journal->j_last_sync_writer != pid) {
|
||||
if (handle->h_sync && journal->j_last_sync_writer != pid &&
|
||||
journal->j_max_batch_time) {
|
||||
u64 commit_time, trans_time;
|
||||
|
||||
journal->j_last_sync_writer = pid;
|
||||
|
|
Loading…
Reference in a new issue