btrfs: lift read-write mount setup from mount and remount
authorBoris Burkov <boris@bur.io>
Wed, 18 Nov 2020 23:06:16 +0000 (15:06 -0800)
committerDavid Sterba <dsterba@suse.com>
Wed, 9 Dec 2020 18:16:07 +0000 (19:16 +0100)
Mounting rw and remounting from ro to rw naturally share invariants and
functionality which result in a correctly setup rw filesystem. Luckily,
there is even a strong unity in the code which implements them. In
mount's open_ctree, these operations mostly happen after an early return
for ro file systems, and in remount, they happen in a section devoted to
remounting ro->rw, after some remount specific validation passes.

However, there are unfortunately a few differences. There are small
deviations in the order of some of the operations, remount does not
start orphan cleanup in root_tree or fs_tree, remount does not create
the free space tree, and remount does not handle "one-shot" mount
options like clear_cache and uuid tree rescan.

Since we want to add building the free space tree to remount, and also
to start the same orphan cleanup process on a filesystem mounted as ro
then remounted rw, we would benefit from unifying the logic between the
two code paths.

This patch only lifts the existing common functionality, and leaves a
natural path for fixing the discrepancies.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/super.c

index 2d8bcd0..c788658 100644 (file)
@@ -2870,6 +2870,52 @@ static int btrfs_check_uuid_tree(struct btrfs_fs_info *fs_info)
        return 0;
 }
 
+/*
+ * Mounting logic specific to read-write file systems. Shared by open_ctree
+ * and btrfs_remount when remounting from read-only to read-write.
+ */
+int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
+{
+       int ret;
+
+       ret = btrfs_cleanup_fs_roots(fs_info);
+       if (ret)
+               goto out;
+
+       mutex_lock(&fs_info->cleaner_mutex);
+       ret = btrfs_recover_relocation(fs_info->tree_root);
+       mutex_unlock(&fs_info->cleaner_mutex);
+       if (ret < 0) {
+               btrfs_warn(fs_info, "failed to recover relocation: %d", ret);
+               goto out;
+       }
+
+       ret = btrfs_resume_balance_async(fs_info);
+       if (ret)
+               goto out;
+
+       ret = btrfs_resume_dev_replace_async(fs_info);
+       if (ret) {
+               btrfs_warn(fs_info, "failed to resume dev_replace");
+               goto out;
+       }
+
+       btrfs_qgroup_rescan_resume(fs_info);
+
+       if (!fs_info->uuid_root) {
+               btrfs_info(fs_info, "creating UUID tree");
+               ret = btrfs_create_uuid_tree(fs_info);
+               if (ret) {
+                       btrfs_warn(fs_info,
+                                  "failed to create the UUID tree %d", ret);
+                       goto out;
+               }
+       }
+
+out:
+       return ret;
+}
+
 int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_devices,
                      char *options)
 {
@@ -3285,22 +3331,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
        if (ret)
                goto fail_qgroup;
 
-       if (!sb_rdonly(sb)) {
-               ret = btrfs_cleanup_fs_roots(fs_info);
-               if (ret)
-                       goto fail_qgroup;
-
-               mutex_lock(&fs_info->cleaner_mutex);
-               ret = btrfs_recover_relocation(tree_root);
-               mutex_unlock(&fs_info->cleaner_mutex);
-               if (ret < 0) {
-                       btrfs_warn(fs_info, "failed to recover relocation: %d",
-                                       ret);
-                       err = -EINVAL;
-                       goto fail_qgroup;
-               }
-       }
-
        fs_info->fs_root = btrfs_get_fs_root(fs_info, BTRFS_FS_TREE_OBJECTID, true);
        if (IS_ERR(fs_info->fs_root)) {
                err = PTR_ERR(fs_info->fs_root);
@@ -3353,35 +3383,16 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
        }
        up_read(&fs_info->cleanup_work_sem);
 
-       ret = btrfs_resume_balance_async(fs_info);
-       if (ret) {
-               btrfs_warn(fs_info, "failed to resume balance: %d", ret);
-               close_ctree(fs_info);
-               return ret;
-       }
-
-       ret = btrfs_resume_dev_replace_async(fs_info);
+       ret = btrfs_start_pre_rw_mount(fs_info);
        if (ret) {
-               btrfs_warn(fs_info, "failed to resume device replace: %d", ret);
                close_ctree(fs_info);
                return ret;
        }
-
-       btrfs_qgroup_rescan_resume(fs_info);
        btrfs_discard_resume(fs_info);
 
-       if (!fs_info->uuid_root) {
-               btrfs_info(fs_info, "creating UUID tree");
-               ret = btrfs_create_uuid_tree(fs_info);
-               if (ret) {
-                       btrfs_warn(fs_info,
-                               "failed to create the UUID tree: %d", ret);
-                       close_ctree(fs_info);
-                       return ret;
-               }
-       } else if (btrfs_test_opt(fs_info, RESCAN_UUID_TREE) ||
-                  fs_info->generation !=
-                               btrfs_super_uuid_tree_generation(disk_super)) {
+       if (fs_info->uuid_root &&
+           (btrfs_test_opt(fs_info, RESCAN_UUID_TREE) ||
+            fs_info->generation != btrfs_super_uuid_tree_generation(disk_super))) {
                btrfs_info(fs_info, "checking UUID tree");
                ret = btrfs_check_uuid_tree(fs_info);
                if (ret) {
index 9844101..b509d1a 100644 (file)
@@ -50,6 +50,7 @@ struct extent_buffer *btrfs_find_create_tree_block(
                                                u64 bytenr, u64 owner_root,
                                                int level);
 void btrfs_clean_tree_block(struct extent_buffer *buf);
+int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info);
 int __cold open_ctree(struct super_block *sb,
               struct btrfs_fs_devices *fs_devices,
               char *options);
index 455d924..49b4a16 100644 (file)
@@ -1885,7 +1885,6 @@ static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
 static int btrfs_remount(struct super_block *sb, int *flags, char *data)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(sb);
-       struct btrfs_root *root = fs_info->tree_root;
        unsigned old_flags = sb->s_flags;
        unsigned long old_opts = fs_info->mount_opt;
        unsigned long old_compress_type = fs_info->compress_type;
@@ -1978,39 +1977,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                        goto restore;
                }
 
-               ret = btrfs_cleanup_fs_roots(fs_info);
-               if (ret)
-                       goto restore;
-
-               /* recover relocation */
-               mutex_lock(&fs_info->cleaner_mutex);
-               ret = btrfs_recover_relocation(root);
-               mutex_unlock(&fs_info->cleaner_mutex);
-               if (ret)
-                       goto restore;
-
-               ret = btrfs_resume_balance_async(fs_info);
+               /*
+                * NOTE: when remounting with a change that does writes, don't
+                * put it anywhere above this point, as we are not sure to be
+                * safe to write until we pass the above checks.
+                */
+               ret = btrfs_start_pre_rw_mount(fs_info);
                if (ret)
                        goto restore;
 
-               ret = btrfs_resume_dev_replace_async(fs_info);
-               if (ret) {
-                       btrfs_warn(fs_info, "failed to resume dev_replace");
-                       goto restore;
-               }
-
-               btrfs_qgroup_rescan_resume(fs_info);
-
-               if (!fs_info->uuid_root) {
-                       btrfs_info(fs_info, "creating UUID tree");
-                       ret = btrfs_create_uuid_tree(fs_info);
-                       if (ret) {
-                               btrfs_warn(fs_info,
-                                          "failed to create the UUID tree %d",
-                                          ret);
-                               goto restore;
-                       }
-               }
                sb->s_flags &= ~SB_RDONLY;
 
                set_bit(BTRFS_FS_OPEN, &fs_info->flags);