mirror of https://gitee.com/openkylin/linux.git
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: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
b2c78cd09b
commit
ce7e010aef
|
@ -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));
|
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);
|
||||||
|
|
||||||
|
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_stripe = ext4_get_stripe_size(sbi);
|
||||||
sbi->s_max_writeback_mb_bump = 128;
|
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);
|
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
|
||||||
ext4_count_free_blocks(sb));
|
* need to update the global counters.
|
||||||
if (!err)
|
*/
|
||||||
err = percpu_counter_init(&sbi->s_freeinodes_counter,
|
percpu_counter_set(&sbi->s_freeblocks_counter,
|
||||||
ext4_count_free_inodes(sb));
|
ext4_count_free_blocks(sb));
|
||||||
if (!err)
|
percpu_counter_set(&sbi->s_freeinodes_counter,
|
||||||
err = percpu_counter_init(&sbi->s_dirs_counter,
|
ext4_count_free_inodes(sb));
|
||||||
ext4_count_dirs(sb));
|
percpu_counter_set(&sbi->s_dirs_counter,
|
||||||
if (!err)
|
ext4_count_dirs(sb));
|
||||||
err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
|
percpu_counter_set(&sbi->s_dirtyblocks_counter, 0);
|
||||||
if (err) {
|
|
||||||
ext4_msg(sb, KERN_ERR, "insufficient memory");
|
|
||||||
goto failed_mount_wq;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
no_journal:
|
||||||
EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
|
EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
|
||||||
if (!EXT4_SB(sb)->dio_unwritten_wq) {
|
if (!EXT4_SB(sb)->dio_unwritten_wq) {
|
||||||
printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
|
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);
|
jbd2_journal_destroy(sbi->s_journal);
|
||||||
sbi->s_journal = NULL;
|
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:
|
failed_mount3:
|
||||||
if (sbi->s_flex_groups) {
|
if (sbi->s_flex_groups) {
|
||||||
if (is_vmalloc_addr(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
|
else
|
||||||
kfree(sbi->s_flex_groups);
|
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:
|
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]);
|
||||||
|
@ -3948,13 +3963,11 @@ static int ext4_commit_super(struct super_block *sb, int sync)
|
||||||
else
|
else
|
||||||
es->s_kbytes_written =
|
es->s_kbytes_written =
|
||||||
cpu_to_le64(EXT4_SB(sb)->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_free_blocks_count_set(es, percpu_counter_sum_positive(
|
&EXT4_SB(sb)->s_freeblocks_counter));
|
||||||
&EXT4_SB(sb)->s_freeblocks_counter));
|
es->s_free_inodes_count =
|
||||||
if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
|
cpu_to_le32(percpu_counter_sum_positive(
|
||||||
es->s_free_inodes_count =
|
&EXT4_SB(sb)->s_freeinodes_counter));
|
||||||
cpu_to_le32(percpu_counter_sum_positive(
|
|
||||||
&EXT4_SB(sb)->s_freeinodes_counter));
|
|
||||||
sb->s_dirt = 0;
|
sb->s_dirt = 0;
|
||||||
BUFFER_TRACE(sbh, "marking dirty");
|
BUFFER_TRACE(sbh, "marking dirty");
|
||||||
mark_buffer_dirty(sbh);
|
mark_buffer_dirty(sbh);
|
||||||
|
|
Loading…
Reference in New Issue