btrfs-progs: allow zoned RAID
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> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
81d6ecd5c2
commit
b4ab282686
|
@ -190,6 +190,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_TO_STRING2(compat, 6,7),
|
||||
VERSION_NULL(safe),
|
||||
VERSION_NULL(default),
|
||||
.desc = "raid stripe tree"
|
||||
},
|
||||
#endif
|
||||
/* Keep this one last */
|
||||
|
|
|
@ -103,7 +103,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;
|
||||
}
|
||||
|
|
74
mkfs/main.c
74
mkfs/main.c
|
@ -962,6 +962,36 @@ 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);
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
return ret;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Thread callback for device preparation */
|
||||
static void *prepare_one_device(void *ctx)
|
||||
{
|
||||
|
@ -1472,10 +1502,38 @@ 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;
|
||||
bool rst = false;
|
||||
|
||||
#if EXPERIMENTAL
|
||||
if (features.incompat_flags & BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE)
|
||||
rst = true;
|
||||
#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 +1643,14 @@ 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);
|
||||
|
|
Loading…
Reference in New Issue