drop ->s_umount around acct_auto_close()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 7 Aug 2014 11:32:06 +0000 (07:32 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 7 Aug 2014 18:40:08 +0000 (14:40 -0400)
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>
fs/super.c

index 52ed93eb63df6fceb78ce317e2de54384bcb8a2b..a369f8964dc1d36764284e7d0b0978a779fc52fd 100644 (file)
@@ -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) {