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

Commit ce7e010a authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

ext4: initialize the percpu counters before replaying the journal



We now initialize the percpu counters before replaying the journal,
but after the journal, we recalculate the global counters, to deal
with the possibility of the per-blockgroup counts getting updated by
the journal replay.

Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent b2c78cd0
Loading
Loading
Loading
Loading
+39 −26
Original line number Diff line number Diff line
@@ -3347,6 +3347,24 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
	spin_lock_init(&sbi->s_next_gen_lock);

	err = percpu_counter_init(&sbi->s_freeblocks_counter,
			ext4_count_free_blocks(sb));
	if (!err) {
		err = percpu_counter_init(&sbi->s_freeinodes_counter,
				ext4_count_free_inodes(sb));
	}
	if (!err) {
		err = percpu_counter_init(&sbi->s_dirs_counter,
				ext4_count_dirs(sb));
	}
	if (!err) {
		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
	}
	if (err) {
		ext4_msg(sb, KERN_ERR, "insufficient memory");
		goto failed_mount3;
	}

	sbi->s_stripe = ext4_get_stripe_size(sbi);
	sbi->s_max_writeback_mb_bump = 128;

@@ -3445,22 +3463,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
	}
	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);

no_journal:
	err = percpu_counter_init(&sbi->s_freeblocks_counter,
	/*
	 * The journal may have updated the bg summary counts, so we
	 * need to update the global counters.
	 */
	percpu_counter_set(&sbi->s_freeblocks_counter,
			   ext4_count_free_blocks(sb));
	if (!err)
		err = percpu_counter_init(&sbi->s_freeinodes_counter,
	percpu_counter_set(&sbi->s_freeinodes_counter,
			   ext4_count_free_inodes(sb));
	if (!err)
		err = percpu_counter_init(&sbi->s_dirs_counter,
	percpu_counter_set(&sbi->s_dirs_counter,
			   ext4_count_dirs(sb));
	if (!err)
		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
	if (err) {
		ext4_msg(sb, KERN_ERR, "insufficient memory");
		goto failed_mount_wq;
	}
	percpu_counter_set(&sbi->s_dirtyblocks_counter, 0);

no_journal:
	EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
	if (!EXT4_SB(sb)->dio_unwritten_wq) {
		printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
@@ -3610,10 +3625,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
		jbd2_journal_destroy(sbi->s_journal);
		sbi->s_journal = NULL;
	}
	percpu_counter_destroy(&sbi->s_freeblocks_counter);
	percpu_counter_destroy(&sbi->s_freeinodes_counter);
	percpu_counter_destroy(&sbi->s_dirs_counter);
	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
failed_mount3:
	if (sbi->s_flex_groups) {
		if (is_vmalloc_addr(sbi->s_flex_groups))
@@ -3621,6 +3632,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
		else
			kfree(sbi->s_flex_groups);
	}
	percpu_counter_destroy(&sbi->s_freeblocks_counter);
	percpu_counter_destroy(&sbi->s_freeinodes_counter);
	percpu_counter_destroy(&sbi->s_dirs_counter);
	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
failed_mount2:
	for (i = 0; i < db_count; i++)
		brelse(sbi->s_group_desc[i]);
@@ -3948,10 +3963,8 @@ static int ext4_commit_super(struct super_block *sb, int sync)
	else
		es->s_kbytes_written =
			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeblocks_counter))
	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
					   &EXT4_SB(sb)->s_freeblocks_counter));
	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
	es->s_free_inodes_count =
		cpu_to_le32(percpu_counter_sum_positive(
				&EXT4_SB(sb)->s_freeinodes_counter));