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

Commit 18b34d9a 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 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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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);
+8 −8
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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
+28 −32
Original line number Diff line number Diff line
@@ -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) {
+4 −1
Original line number Diff line number Diff line
@@ -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;