diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-08-07 07:32:06 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-08-07 14:40:08 -0400 |
commit | 0aec09d049d7e994eba54bad4376dd8f58eab797 (patch) | |
tree | 220068a33da8eadd95e3006f626f3d80b8822f6b /fs/super.c | |
parent | 2798d4ce61601808b965253d60624bbf201b51b0 (diff) | |
download | linux-0aec09d049d7e994eba54bad4376dd8f58eab797.tar.gz linux-0aec09d049d7e994eba54bad4376dd8f58eab797.tar.bz2 linux-0aec09d049d7e994eba54bad4376dd8f58eab797.zip |
drop ->s_umount around acct_auto_close()
just repeat the frozen check after regaining it, and check that sb
is still alive. If several threads hit acct_auto_close() at the
same time, acct_auto_close() will survive that just fine. And we
really don't want to play with writes and closing the file with
->s_umount held exclusive - it's a deadlock country.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/super.c b/fs/super.c index 52ed93eb63df..a369f8964dc1 100644 --- a/fs/super.c +++ b/fs/super.c @@ -702,12 +702,22 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) return -EACCES; #endif - if (flags & MS_RDONLY) - acct_auto_close(&sb->s_pins); - shrink_dcache_sb(sb); - remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); + if (remount_ro) { + if (sb->s_pins.first) { + up_write(&sb->s_umount); + acct_auto_close(&sb->s_pins); + down_write(&sb->s_umount); + if (!sb->s_root) + return 0; + if (sb->s_writers.frozen != SB_UNFROZEN) + return -EBUSY; + remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); + } + } + shrink_dcache_sb(sb); + /* If we are remounting RDONLY and current sb is read/write, make sure there are no rw files opened */ if (remount_ro) { |