diff options
author | Jan Kara <jack@suse.cz> | 2017-04-05 13:32:52 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2017-04-05 14:23:45 +0200 |
commit | 65547661500885dde26ca4a75d4d7f7df587c88e (patch) | |
tree | 72f05ce433afc3249d1ec242679c4c04d041e9e2 /fs | |
parent | ab4949640d6674b617b314ad3c2c00353304bab9 (diff) | |
download | op-kernel-dev-65547661500885dde26ca4a75d4d7f7df587c88e.zip op-kernel-dev-65547661500885dde26ca4a75d4d7f7df587c88e.tar.gz |
ext2: Call dquot_writeback_dquots() with s_umount held
ext2_sync_fs() could be called without s_umount semaphore held when
called through ext2_write_super() from __ext2_write_inode(). This
function then calls dquot_writeback_dquots() which relies on s_umount to
be held for protection against other quota operations.
In fact __ext2_write_inode() does not need all the functionality
ext2_write_super() provides. It is enough to just write the superblock.
So use ext2_sync_super() instead.
Fixes: 9d1ccbe70e0b14545caad12dc73adb3605447df0
Reported-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext2/ext2.h | 3 | ||||
-rw-r--r-- | fs/ext2/inode.c | 2 | ||||
-rw-r--r-- | fs/ext2/super.c | 9 |
3 files changed, 7 insertions, 7 deletions
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 5e64de9..dca3604 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -796,7 +796,8 @@ void ext2_error(struct super_block *, const char *, const char *, ...); extern __printf(3, 4) void ext2_msg(struct super_block *, const char *, const char *, ...); extern void ext2_update_dynamic_rev (struct super_block *sb); -extern void ext2_write_super (struct super_block *); +extern void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es, + int wait); /* * Inodes and files operations diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 128cce5..4d3e252 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1615,7 +1615,7 @@ static int __ext2_write_inode(struct inode *inode, int do_sync) EXT2_SET_RO_COMPAT_FEATURE(sb, EXT2_FEATURE_RO_COMPAT_LARGE_FILE); spin_unlock(&EXT2_SB(sb)->s_lock); - ext2_write_super(sb); + ext2_sync_super(sb, EXT2_SB(sb)->s_es, 1); } } } diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 9e25a71..b309041 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -36,8 +36,7 @@ #include "xattr.h" #include "acl.h" -static void ext2_sync_super(struct super_block *sb, - struct ext2_super_block *es, int wait); +static void ext2_write_super(struct super_block *sb); static int ext2_remount (struct super_block * sb, int * flags, char * data); static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); static int ext2_sync_fs(struct super_block *sb, int wait); @@ -1194,8 +1193,8 @@ static void ext2_clear_super_error(struct super_block *sb) } } -static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es, - int wait) +void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es, + int wait) { ext2_clear_super_error(sb); spin_lock(&EXT2_SB(sb)->s_lock); @@ -1270,7 +1269,7 @@ static int ext2_unfreeze(struct super_block *sb) return 0; } -void ext2_write_super(struct super_block *sb) +static void ext2_write_super(struct super_block *sb) { if (!(sb->s_flags & MS_RDONLY)) ext2_sync_fs(sb, 1); |