Merge tag 'imx-fixes-5.11-3' of git://git.kernel.org/pub/scm/linux/kernel/git/shawngu...
[linux-2.6-microblaze.git] / fs / btrfs / super.c
index 022f208..12d7d3b 100644 (file)
@@ -175,7 +175,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
        btrfs_discard_stop(fs_info);
 
        /* btrfs handle error by forcing the filesystem readonly */
-       sb->s_flags |= SB_RDONLY;
+       btrfs_set_sb_rdonly(sb);
        btrfs_info(fs_info, "forced readonly");
        /*
         * Note that a running device replace operation is not canceled here
@@ -1953,7 +1953,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                /* avoid complains from lockdep et al. */
                up(&fs_info->uuid_tree_rescan_sem);
 
-               sb->s_flags |= SB_RDONLY;
+               btrfs_set_sb_rdonly(sb);
 
                /*
                 * Setting SB_RDONLY will put the cleaner thread to
@@ -1964,10 +1964,42 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                 */
                btrfs_delete_unused_bgs(fs_info);
 
+               /*
+                * The cleaner task could be already running before we set the
+                * flag BTRFS_FS_STATE_RO (and SB_RDONLY in the superblock).
+                * We must make sure that after we finish the remount, i.e. after
+                * we call btrfs_commit_super(), the cleaner can no longer start
+                * a transaction - either because it was dropping a dead root,
+                * running delayed iputs or deleting an unused block group (the
+                * cleaner picked a block group from the list of unused block
+                * groups before we were able to in the previous call to
+                * btrfs_delete_unused_bgs()).
+                */
+               wait_on_bit(&fs_info->flags, BTRFS_FS_CLEANER_RUNNING,
+                           TASK_UNINTERRUPTIBLE);
+
+               /*
+                * We've set the superblock to RO mode, so we might have made
+                * the cleaner task sleep without running all pending delayed
+                * iputs. Go through all the delayed iputs here, so that if an
+                * unmount happens without remounting RW we don't end up at
+                * finishing close_ctree() with a non-empty list of delayed
+                * iputs.
+                */
+               btrfs_run_delayed_iputs(fs_info);
+
                btrfs_dev_replace_suspend_for_unmount(fs_info);
                btrfs_scrub_cancel(fs_info);
                btrfs_pause_balance(fs_info);
 
+               /*
+                * Pause the qgroup rescan worker if it is running. We don't want
+                * it to be still running after we are in RO mode, as after that,
+                * by the time we unmount, it might have left a transaction open,
+                * so we would leak the transaction and/or crash.
+                */
+               btrfs_qgroup_wait_for_completion(fs_info, false);
+
                ret = btrfs_commit_super(fs_info);
                if (ret)
                        goto restore;
@@ -2006,7 +2038,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                if (ret)
                        goto restore;
 
-               sb->s_flags &= ~SB_RDONLY;
+               btrfs_clear_sb_rdonly(sb);
 
                set_bit(BTRFS_FS_OPEN, &fs_info->flags);
        }
@@ -2028,6 +2060,8 @@ restore:
        /* We've hit an error - don't reset SB_RDONLY */
        if (sb_rdonly(sb))
                old_flags |= SB_RDONLY;
+       if (!(old_flags & SB_RDONLY))
+               clear_bit(BTRFS_FS_STATE_RO, &fs_info->fs_state);
        sb->s_flags = old_flags;
        fs_info->mount_opt = old_opts;
        fs_info->compress_type = old_compress_type;