Commit 44c0ca21 authored by Boris Burkov's avatar Boris Burkov Committed by David Sterba
Browse files

btrfs: lift read-write mount setup from mount and remount



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: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarBoris Burkov <boris@bur.io>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 47876f7c
Loading
Loading
Loading
Loading
+50 −39
Original line number Diff line number Diff line
@@ -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);
	ret = btrfs_start_pre_rw_mount(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);
	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) {
+1 −0
Original line number Diff line number Diff line
@@ -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);
+6 −31
Original line number Diff line number Diff line
@@ -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);