aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorDaeho Jeong <daeho.jeong@samsung.com>2016-04-25 23:22:35 -0400
committerTheodore Ts'o <tytso@mit.edu>2016-04-25 23:22:35 -0400
commitc8585c6fcaf2011de54c3592e80a634a2b9e1a7f (patch)
tree66b440a3e710ab4b63ae20200735a594bffb74cd /fs/ext4/super.c
parent4c54659269ecb799133758330e7ea2a6fa4c65ca (diff)
ext4: fix races between changing inode journal mode and ext4_writepages
In ext4, there is a race condition between changing inode journal mode and ext4_writepages(). While ext4_writepages() is executed on a non-journalled mode inode, the inode's journal mode could be enabled by ioctl() and then, some pages dirtied after switching the journal mode will be still exposed to ext4_writepages() in non-journaled mode. To resolve this problem, we use fs-wide per-cpu rw semaphore by Jan Kara's suggestion because we don't want to waste ext4_inode_info's space for this extra rare case. Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 304c712dbe12..20c5d52253b4 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -859,6 +859,7 @@ static void ext4_put_super(struct super_block *sb)
859 percpu_counter_destroy(&sbi->s_freeinodes_counter); 859 percpu_counter_destroy(&sbi->s_freeinodes_counter);
860 percpu_counter_destroy(&sbi->s_dirs_counter); 860 percpu_counter_destroy(&sbi->s_dirs_counter);
861 percpu_counter_destroy(&sbi->s_dirtyclusters_counter); 861 percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
862 percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
862 brelse(sbi->s_sbh); 863 brelse(sbi->s_sbh);
863#ifdef CONFIG_QUOTA 864#ifdef CONFIG_QUOTA
864 for (i = 0; i < EXT4_MAXQUOTAS; i++) 865 for (i = 0; i < EXT4_MAXQUOTAS; i++)
@@ -3930,6 +3931,9 @@ no_journal:
3930 if (!err) 3931 if (!err)
3931 err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0, 3932 err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
3932 GFP_KERNEL); 3933 GFP_KERNEL);
3934 if (!err)
3935 err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem);
3936
3933 if (err) { 3937 if (err) {
3934 ext4_msg(sb, KERN_ERR, "insufficient memory"); 3938 ext4_msg(sb, KERN_ERR, "insufficient memory");
3935 goto failed_mount6; 3939 goto failed_mount6;