@@ -189,6 +189,14 @@ static const struct btrfs_feature mkfs_features[] = {
VERSION_NULL(safe),
VERSION_NULL(default),
.desc = "new extent tree format"
+ } , {
+ .name = "raid-stripe-tree",
+ .incompat_flag = BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE,
+ .sysfs_name = NULL,
+ VERSION_NULL(compat),
+ VERSION_NULL(safe),
+ VERSION_NULL(default),
+ .desc = "raid stripe tree"
},
#endif
/* Keep this one last */
@@ -102,7 +102,8 @@ static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 nodesize)
BTRFS_FEATURE_INCOMPAT_RAID1C34 | \
BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \
BTRFS_FEATURE_INCOMPAT_ZONED | \
- BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2)
+ BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 | \
+ BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE)
#else
#define BTRFS_FEATURE_INCOMPAT_SUPP \
(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
@@ -737,7 +737,7 @@ out:
return ret;
}
-bool zoned_profile_supported(u64 map_type)
+bool zoned_profile_supported(u64 map_type, bool rst)
{
bool data = (map_type & BTRFS_BLOCK_GROUP_DATA);
u64 flags = (map_type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
@@ -746,9 +746,37 @@ bool zoned_profile_supported(u64 map_type)
if (flags == 0)
return true;
- /* We can support DUP on metadata */
+#if EXPERIMENTAL
+ if (data) {
+ if ((flags & BTRFS_BLOCK_GROUP_DUP) && rst)
+ return true;
+ /* Data RAID1 needs a raid-stripe-tree */
+ if ((flags & BTRFS_BLOCK_GROUP_RAID1_MASK) && rst)
+ return true;
+ /* Data RAID0 needs a raid-stripe-tree */
+ if ((flags & BTRFS_BLOCK_GROUP_RAID0) && rst)
+ return true;
+ /* Data RAID10 needs a raid-stripe-tree */
+ if ((flags & BTRFS_BLOCK_GROUP_RAID10) && rst)
+ return true;
+ } else {
+ /* We can support DUP on metadata/system */
+ if (flags & BTRFS_BLOCK_GROUP_DUP)
+ return true;
+ /* We can support RAID1 on metadata/system */
+ if (flags & BTRFS_BLOCK_GROUP_RAID1_MASK)
+ return true;
+ /* We can support RAID0 on metadata/system */
+ if (flags & BTRFS_BLOCK_GROUP_RAID0)
+ return true;
+ /* We can support RAID10 on metadata/system */
+ if (flags & BTRFS_BLOCK_GROUP_RAID10)
+ return true;
+ }
+#else
if (!data && (flags & BTRFS_BLOCK_GROUP_DUP))
return true;
+#endif
/* All other profiles are not supported yet */
return false;
@@ -863,7 +891,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_fs_info *fs_info,
}
}
- if (!zoned_profile_supported(map->type)) {
+ if (!zoned_profile_supported(map->type, !!fs_info->stripe_root)) {
error("zoned: profile %s not yet supported",
btrfs_group_profile_str(map->type));
ret = -EINVAL;
@@ -133,7 +133,7 @@ static inline bool btrfs_dev_is_empty_zone(struct btrfs_device *device, u64 pos)
return zinfo->zones[zno].cond == BLK_ZONE_COND_EMPTY;
}
-bool zoned_profile_supported(u64 map_type);
+bool zoned_profile_supported(u64 map_type, bool rst);
int btrfs_reset_dev_zone(int fd, struct blk_zone *zone);
u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start,
u64 hole_end, u64 num_bytes);
@@ -214,7 +214,7 @@ static inline int btrfs_wipe_temporary_sb(struct btrfs_fs_devices *fs_devices)
return 0;
}
-static inline bool zoned_profile_supported(u64 map_type)
+static inline bool zoned_profile_supported(u64 map_type, bool rst)
{
return false;
}
@@ -962,6 +962,38 @@ fail:
return ret;
}
+static int setup_raid_stripe_tree_root(struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *stripe_root;
+ struct btrfs_key key = {
+ .objectid = BTRFS_RAID_STRIPE_TREE_OBJECTID,
+ .type = BTRFS_ROOT_ITEM_KEY,
+ };
+ int ret;
+
+ trans = btrfs_start_transaction(fs_info->tree_root, 0);
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+ stripe_root = btrfs_create_tree(trans, fs_info, &key);
+ if (IS_ERR(stripe_root)) {
+ ret = PTR_ERR(stripe_root);
+ goto abort;
+ }
+ fs_info->stripe_root = stripe_root;
+ add_root_to_dirty_list(stripe_root);
+
+ ret = btrfs_commit_transaction(trans, fs_info->tree_root);
+ if (ret)
+ return ret;
+
+ return 0;
+abort:
+ btrfs_abort_transaction(trans, ret);
+ return ret;
+}
+
/* Thread callback for device preparation */
static void *prepare_one_device(void *ctx)
{
@@ -1472,10 +1504,39 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
if (ret)
goto error;
- if (opt_zoned && (!zoned_profile_supported(BTRFS_BLOCK_GROUP_METADATA | metadata_profile) ||
- !zoned_profile_supported(BTRFS_BLOCK_GROUP_DATA | data_profile))) {
- error("zoned mode does not yet support RAID/DUP profiles, please specify '-d single -m single' manually");
- goto error;
+#if EXPERIMENTAL
+ if (opt_zoned && device_count) {
+ switch (data_profile & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+ case BTRFS_BLOCK_GROUP_DUP:
+ case BTRFS_BLOCK_GROUP_RAID1:
+ case BTRFS_BLOCK_GROUP_RAID1C3:
+ case BTRFS_BLOCK_GROUP_RAID1C4:
+ case BTRFS_BLOCK_GROUP_RAID0:
+ case BTRFS_BLOCK_GROUP_RAID10:
+ features.incompat_flags |=
+ BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE;
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+
+ if (opt_zoned) {
+ u64 metadata = BTRFS_BLOCK_GROUP_METADATA | metadata_profile;
+ u64 data = BTRFS_BLOCK_GROUP_DATA | data_profile;
+#if EXPERIMENTAL
+ bool rst = features.incompat_flags &
+ BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE;
+#else
+ bool rst = false;
+#endif
+
+ if (!zoned_profile_supported(metadata, rst) ||
+ !zoned_profile_supported(data, rst)) {
+ error("zoned mode does not yet support RAID/DUP profiles, please specify '-d single -m single' manually");
+ goto error;
+ }
}
t_prepare = calloc(device_count, sizeof(*t_prepare));
@@ -1585,6 +1646,15 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
goto error;
}
+ if (features.incompat_flags & BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE) {
+ ret = setup_raid_stripe_tree_root(fs_info);
+ if (ret < 0) {
+ error("failed to initialize raid-stripe-tree: %d (%m)",
+ ret);
+ goto out;
+ }
+ }
+
trans = btrfs_start_transaction(root, 1);
if (IS_ERR(trans)) {
errno = -PTR_ERR(trans);
@@ -1750,6 +1820,7 @@ raid_groups:
goto out;
}
}
+
if (bconf.verbose) {
char features_buf[BTRFS_FEATURE_STRING_BUF_SIZE];
Allow for RAID levels 0, 1 and 10 on zoned devices if the RAID stripe tree is used. Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> --- common/fsfeatures.c | 8 ++++++ kernel-shared/ctree.h | 3 +- kernel-shared/zoned.c | 34 ++++++++++++++++++++-- kernel-shared/zoned.h | 4 +-- mkfs/main.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 118 insertions(+), 10 deletions(-)