Commit 0b4d29fa authored by Mark Harmstone's avatar Mark Harmstone Committed by David Sterba
Browse files

btrfs: add METADATA_REMAP chunk type



Add a new METADATA_REMAP chunk type, which is a metadata chunk that holds the
remap tree.

This is needed for bootstrapping purposes: the remap tree can't itself
be remapped, and must be relocated the existing way, by COWing every
leaf. The remap tree can't go in the SYSTEM chunk as space there is
limited, because a copy of the chunk item gets placed in the superblock.

The changes in fs/btrfs/volumes.h are because we're adding a new block
group type bit after the profile bits, and so can no longer rely on the
const_ilog2 trick.

The sizing to 32MB per chunk, matching the SYSTEM chunk, is an estimate
here, we can adjust it later if it proves to be too big or too small.
This works out to be ~500,000 remap items, which for a 4KB block size
covers ~2GB of remapped data in the worst case and ~500TB in the best case.

Reviewed-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarMark Harmstone <mark@harmstone.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ef6a31d0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -419,6 +419,9 @@ void btrfs_init_root_block_rsv(struct btrfs_root *root)
	case BTRFS_TREE_LOG_OBJECTID:
		root->block_rsv = &fs_info->treelog_rsv;
		break;
	case BTRFS_REMAP_TREE_OBJECTID:
		root->block_rsv = &fs_info->remap_block_rsv;
		break;
	default:
		root->block_rsv = NULL;
		break;
@@ -432,6 +435,9 @@ void btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info)
	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM);
	fs_info->chunk_block_rsv.space_info = space_info;

	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA_REMAP);
	fs_info->remap_block_rsv.space_info = space_info;

	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
	fs_info->global_block_rsv.space_info = space_info;
	fs_info->trans_block_rsv.space_info = space_info;
@@ -458,6 +464,8 @@ void btrfs_release_global_block_rsv(struct btrfs_fs_info *fs_info)
	WARN_ON(fs_info->trans_block_rsv.reserved > 0);
	WARN_ON(fs_info->chunk_block_rsv.size > 0);
	WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
	WARN_ON(fs_info->remap_block_rsv.size > 0);
	WARN_ON(fs_info->remap_block_rsv.reserved > 0);
	WARN_ON(fs_info->delayed_block_rsv.size > 0);
	WARN_ON(fs_info->delayed_block_rsv.reserved > 0);
	WARN_ON(fs_info->delayed_refs_rsv.reserved > 0);
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ enum btrfs_rsv_type {
	BTRFS_BLOCK_RSV_DELALLOC,
	BTRFS_BLOCK_RSV_TRANS,
	BTRFS_BLOCK_RSV_CHUNK,
	BTRFS_BLOCK_RSV_REMAP,
	BTRFS_BLOCK_RSV_DELOPS,
	BTRFS_BLOCK_RSV_DELREFS,
	BTRFS_BLOCK_RSV_TREELOG,
+1 −0
Original line number Diff line number Diff line
@@ -2751,6 +2751,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
			     BTRFS_BLOCK_RSV_GLOBAL);
	btrfs_init_block_rsv(&fs_info->trans_block_rsv, BTRFS_BLOCK_RSV_TRANS);
	btrfs_init_block_rsv(&fs_info->chunk_block_rsv, BTRFS_BLOCK_RSV_CHUNK);
	btrfs_init_block_rsv(&fs_info->remap_block_rsv, BTRFS_BLOCK_RSV_REMAP);
	btrfs_init_block_rsv(&fs_info->treelog_rsv, BTRFS_BLOCK_RSV_TREELOG);
	btrfs_init_block_rsv(&fs_info->empty_block_rsv, BTRFS_BLOCK_RSV_EMPTY);
	btrfs_init_block_rsv(&fs_info->delayed_block_rsv,
+2 −0
Original line number Diff line number Diff line
@@ -509,6 +509,8 @@ struct btrfs_fs_info {
	struct btrfs_block_rsv trans_block_rsv;
	/* Block reservation for chunk tree */
	struct btrfs_block_rsv chunk_block_rsv;
	/* Block reservation for remap tree. */
	struct btrfs_block_rsv remap_block_rsv;
	/* Block reservation for delayed operations */
	struct btrfs_block_rsv delayed_block_rsv;
	/* Block reservation for delayed refs */
+12 −1
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ static u64 calc_chunk_size(const struct btrfs_fs_info *fs_info, u64 flags)

	if (flags & BTRFS_BLOCK_GROUP_DATA)
		return BTRFS_MAX_DATA_CHUNK_SIZE;
	else if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
	else if (flags & (BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA_REMAP))
		return SZ_32M;

	/* Handle BTRFS_BLOCK_GROUP_METADATA */
@@ -348,6 +348,8 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
	if (mixed) {
		flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
		ret = create_space_info(fs_info, flags);
		if (ret)
			goto out;
	} else {
		flags = BTRFS_BLOCK_GROUP_METADATA;
		ret = create_space_info(fs_info, flags);
@@ -356,7 +358,15 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)

		flags = BTRFS_BLOCK_GROUP_DATA;
		ret = create_space_info(fs_info, flags);
		if (ret)
			goto out;
	}

	if (features & BTRFS_FEATURE_INCOMPAT_REMAP_TREE) {
		flags = BTRFS_BLOCK_GROUP_METADATA_REMAP;
		ret = create_space_info(fs_info, flags);
	}

out:
	return ret;
}
@@ -611,6 +621,7 @@ static void dump_global_block_rsv(struct btrfs_fs_info *fs_info)
	DUMP_BLOCK_RSV(fs_info, global_block_rsv);
	DUMP_BLOCK_RSV(fs_info, trans_block_rsv);
	DUMP_BLOCK_RSV(fs_info, chunk_block_rsv);
	DUMP_BLOCK_RSV(fs_info, remap_block_rsv);
	DUMP_BLOCK_RSV(fs_info, delayed_block_rsv);
	DUMP_BLOCK_RSV(fs_info, delayed_refs_rsv);
}
Loading