From b6490733a8585bcd3a5089d3f4628e55f4042664 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 14 Sep 2023 09:05:33 -0700 Subject: [PATCH] btrfs-progs: read fs with stripe tree from disk When encountering a filesystem formatted with the raid stripe tree feature, read it from disk. Also add the incompat declaration to the tree printer. Signed-off-by: Johannes Thumshirn Signed-off-by: David Sterba --- kernel-shared/ctree.h | 1 + kernel-shared/disk-io.c | 26 +++++++++++++++++++++++++- kernel-shared/print-tree.c | 1 + kernel-shared/uapi/btrfs.h | 1 + kernel-shared/uapi/btrfs_tree.h | 3 +++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 59533879..b59387b4 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -306,6 +306,7 @@ struct btrfs_fs_info { struct btrfs_root *quota_root; struct btrfs_root *uuid_root; struct btrfs_root *block_group_root; + struct btrfs_root *stripe_root; struct rb_root global_roots_tree; struct rb_root fs_root_tree; diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 1ef28ba3..88163ac1 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -790,6 +790,9 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, return fs_info->block_group_root ? fs_info->block_group_root : ERR_PTR(-ENOENT); + if (location->objectid == BTRFS_RAID_STRIPE_TREE_OBJECTID) + return fs_info->stripe_root ? fs_info->stripe_root : ERR_PTR(-ENOENT); + BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID); node = rb_search(&fs_info->fs_root_tree, (void *)&objectid, @@ -822,6 +825,9 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info) if (fs_info->quota_root) free(fs_info->quota_root); + if (fs_info->stripe_root) + free(fs_info->stripe_root); + free_global_roots_tree(&fs_info->global_roots_tree); free(fs_info->tree_root); free(fs_info->chunk_root); @@ -846,12 +852,14 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr) fs_info->dev_root = calloc(1, sizeof(struct btrfs_root)); fs_info->quota_root = calloc(1, sizeof(struct btrfs_root)); fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root)); + fs_info->stripe_root = calloc(1, sizeof(struct btrfs_root)); fs_info->block_group_root = calloc(1, sizeof(struct btrfs_root)); fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE); if (!fs_info->tree_root || !fs_info->chunk_root || !fs_info->dev_root || !fs_info->quota_root || !fs_info->uuid_root || - !fs_info->block_group_root || !fs_info->super_copy) + !fs_info->block_group_root || !fs_info->super_copy || + !fs_info->stripe_root) goto free_all; extent_buffer_init_cache(fs_info); @@ -1260,6 +1268,20 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr, return -EIO; } +#if EXPERIMENTAL + if (btrfs_fs_incompat(fs_info, RAID_STRIPE_TREE)) { + ret = btrfs_find_and_setup_root(root, fs_info, + BTRFS_RAID_STRIPE_TREE_OBJECTID, + fs_info->stripe_root); + if (ret) { + free(fs_info->stripe_root); + fs_info->stripe_root = NULL; + } else { + set_bit(BTRFS_ROOT_TRACK_DIRTY, &fs_info->stripe_root->state); + } + } +#endif + if (maybe_load_block_groups(fs_info, flags)) { ret = btrfs_read_block_groups(fs_info); /* @@ -1317,6 +1339,8 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info) free_extent_buffer(fs_info->chunk_root->node); if (fs_info->uuid_root) free_extent_buffer(fs_info->uuid_root->node); + if (fs_info->stripe_root) + free_extent_buffer(fs_info->stripe_root->node); } static void free_map_lookup(struct cache_extent *ce) diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c index d7ffeccd..d70f3d03 100644 --- a/kernel-shared/print-tree.c +++ b/kernel-shared/print-tree.c @@ -1708,6 +1708,7 @@ static struct readable_flag_entry incompat_flags_array[] = { DEF_INCOMPAT_FLAG_ENTRY(RAID1C34), DEF_INCOMPAT_FLAG_ENTRY(ZONED), DEF_INCOMPAT_FLAG_ENTRY(EXTENT_TREE_V2), + DEF_INCOMPAT_FLAG_ENTRY(RAID_STRIPE_TREE), }; static const int incompat_flags_num = sizeof(incompat_flags_array) / sizeof(struct readable_flag_entry); diff --git a/kernel-shared/uapi/btrfs.h b/kernel-shared/uapi/btrfs.h index 85b04f89..c750b7aa 100644 --- a/kernel-shared/uapi/btrfs.h +++ b/kernel-shared/uapi/btrfs.h @@ -356,6 +356,7 @@ _static_assert(sizeof(struct btrfs_ioctl_fs_info_args) == 1024); #define BTRFS_FEATURE_INCOMPAT_RAID1C34 (1ULL << 11) #define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12) #define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13) +#define BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE (1ULL << 14) struct btrfs_ioctl_feature_flags { __u64 compat_flags; diff --git a/kernel-shared/uapi/btrfs_tree.h b/kernel-shared/uapi/btrfs_tree.h index 53597f3b..8d8898b9 100644 --- a/kernel-shared/uapi/btrfs_tree.h +++ b/kernel-shared/uapi/btrfs_tree.h @@ -73,6 +73,9 @@ /* Holds the block group items for extent tree v2. */ #define BTRFS_BLOCK_GROUP_TREE_OBJECTID 11ULL +/* Holds raid stripe entries */ +#define BTRFS_RAID_STRIPE_TREE_OBJECTID 12ULL + /* device stats in the device tree */ #define BTRFS_DEV_STATS_OBJECTID 0ULL