Commit 18b34d9a authored by Linus Torvalds's avatar Linus Torvalds

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
parents 502fde1a bf40c926
...@@ -966,10 +966,10 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, ...@@ -966,10 +966,10 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
continue; 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; continue;
write_lock(&ei->i_es_lock);
shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan); shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
if (ei->i_es_lru_nr == 0) if (ei->i_es_lru_nr == 0)
list_del_init(&ei->i_es_lru); list_del_init(&ei->i_es_lru);
......
...@@ -338,7 +338,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) ...@@ -338,7 +338,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
fatal = err; fatal = err;
} else { } else {
ext4_error(sb, "bit already cleared for inode %lu", ino); 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; int count;
count = ext4_free_inodes_count(sb, gdp); count = ext4_free_inodes_count(sb, gdp);
percpu_counter_sub(&sbi->s_freeinodes_counter, percpu_counter_sub(&sbi->s_freeinodes_counter,
...@@ -874,6 +874,13 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, ...@@ -874,6 +874,13 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
goto out; 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 */ /* We may have to initialize the block bitmap if it isn't already */
if (ext4_has_group_desc_csum(sb) && if (ext4_has_group_desc_csum(sb) &&
gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
...@@ -910,13 +917,6 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, ...@@ -910,13 +917,6 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
} }
} }
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 */ /* Update the relevant bg descriptor fields */
if (ext4_has_group_desc_csum(sb)) { if (ext4_has_group_desc_csum(sb)) {
int free; int free;
......
...@@ -752,8 +752,8 @@ void ext4_mb_generate_buddy(struct super_block *sb, ...@@ -752,8 +752,8 @@ void ext4_mb_generate_buddy(struct super_block *sb,
if (free != grp->bb_free) { if (free != grp->bb_free) {
ext4_grp_locked_error(sb, group, 0, 0, ext4_grp_locked_error(sb, group, 0, 0,
"%u clusters in bitmap, %u in gd; " "block bitmap and bg descriptor "
"block bitmap corrupt.", "inconsistent: %u vs %u free clusters",
free, grp->bb_free); free, grp->bb_free);
/* /*
* If we intend to continue, we consider group descriptor * 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, ...@@ -1525,8 +1525,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
arg = JBD2_DEFAULT_MAX_COMMIT_AGE; arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
sbi->s_commit_interval = HZ * arg; sbi->s_commit_interval = HZ * arg;
} else if (token == Opt_max_batch_time) { } else if (token == Opt_max_batch_time) {
if (arg == 0)
arg = EXT4_DEF_MAX_BATCH_TIME;
sbi->s_max_batch_time = arg; sbi->s_max_batch_time = arg;
} else if (token == Opt_min_batch_time) { } else if (token == Opt_min_batch_time) {
sbi->s_min_batch_time = arg; sbi->s_min_batch_time = arg;
...@@ -2809,10 +2807,11 @@ static void print_daily_error_info(unsigned long arg) ...@@ -2809,10 +2807,11 @@ static void print_daily_error_info(unsigned long arg)
es = sbi->s_es; es = sbi->s_es;
if (es->s_error_count) 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)); le32_to_cpu(es->s_error_count));
if (es->s_first_error_time) { 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), sb->s_id, le32_to_cpu(es->s_first_error_time),
(int) sizeof(es->s_first_error_func), (int) sizeof(es->s_first_error_func),
es->s_first_error_func, es->s_first_error_func,
...@@ -2826,7 +2825,7 @@ static void print_daily_error_info(unsigned long arg) ...@@ -2826,7 +2825,7 @@ static void print_daily_error_info(unsigned long arg)
printk("\n"); printk("\n");
} }
if (es->s_last_error_time) { 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), sb->s_id, le32_to_cpu(es->s_last_error_time),
(int) sizeof(es->s_last_error_func), (int) sizeof(es->s_last_error_func),
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) ...@@ -3880,38 +3879,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount2; 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)) { if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); 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_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
if (!ext4_fill_flex_info(sb)) { if (!ext4_fill_flex_info(sb)) {
ext4_msg(sb, KERN_ERR, ext4_msg(sb, KERN_ERR,
"unable to initialize " "unable to initialize "
"flex_bg meta info!"); "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)); get_random_bytes(&sbi->s_next_generation, sizeof(u32));
spin_lock_init(&sbi->s_next_gen_lock); 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) ...@@ -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_stripe = ext4_get_stripe_size(sbi);
sbi->s_extent_max_zeroout_kb = 32; 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_export_op = &ext4_export_ops;
sb->s_xattr = ext4_xattr_handlers; sb->s_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
...@@ -4135,13 +4123,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -4135,13 +4123,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
if (err) { if (err) {
ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for " ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
"reserved pool", ext4_calculate_resv_clusters(sb)); "reserved pool", ext4_calculate_resv_clusters(sb));
goto failed_mount5; goto failed_mount4a;
} }
err = ext4_setup_system_zone(sb); err = ext4_setup_system_zone(sb);
if (err) { if (err) {
ext4_msg(sb, KERN_ERR, "failed to initialize system " ext4_msg(sb, KERN_ERR, "failed to initialize system "
"zone (%d)", err); "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; goto failed_mount5;
} }
...@@ -4218,8 +4214,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -4218,8 +4214,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
failed_mount7: failed_mount7:
ext4_unregister_li_request(sb); ext4_unregister_li_request(sb);
failed_mount6: failed_mount6:
ext4_release_system_zone(sb); ext4_mb_release(sb);
failed_mount5: failed_mount5:
ext4_ext_release(sb);
ext4_release_system_zone(sb);
failed_mount4a:
dput(sb->s_root); dput(sb->s_root);
sb->s_root = NULL; sb->s_root = NULL;
failed_mount4: failed_mount4:
...@@ -4243,14 +4242,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -4243,14 +4242,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
percpu_counter_destroy(&sbi->s_extent_cache_cnt); percpu_counter_destroy(&sbi->s_extent_cache_cnt);
if (sbi->s_mmp_tsk) if (sbi->s_mmp_tsk)
kthread_stop(sbi->s_mmp_tsk); kthread_stop(sbi->s_mmp_tsk);
failed_mount2a:
ext4_mb_release(sb);
failed_mount2: failed_mount2:
for (i = 0; i < db_count; i++) for (i = 0; i < db_count; i++)
brelse(sbi->s_group_desc[i]); brelse(sbi->s_group_desc[i]);
ext4_kvfree(sbi->s_group_desc); ext4_kvfree(sbi->s_group_desc);
failed_mount: failed_mount:
ext4_ext_release(sb);
if (sbi->s_chksum_driver) if (sbi->s_chksum_driver)
crypto_free_shash(sbi->s_chksum_driver); crypto_free_shash(sbi->s_chksum_driver);
if (sbi->s_proc) { if (sbi->s_proc) {
......
...@@ -1588,9 +1588,12 @@ int jbd2_journal_stop(handle_t *handle) ...@@ -1588,9 +1588,12 @@ int jbd2_journal_stop(handle_t *handle)
* to perform a synchronous write. We do this to detect the * to perform a synchronous write. We do this to detect the
* case where a single process is doing a stream of sync * case where a single process is doing a stream of sync
* writes. No point in waiting for joiners in that case. * writes. No point in waiting for joiners in that case.
*
* Setting max_batch_time to 0 disables this completely.
*/ */
pid = current->pid; 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; u64 commit_time, trans_time;
journal->j_last_sync_writer = pid; journal->j_last_sync_writer = pid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment