module/raid: check for existing superblock on a base_bdev
When adding a new base bdev to a raid bdev (currently only when creating a new raid bdev) make sure that there is no existing superblock stored on the base bdev. This prevents accidentally overwriting a base bdev belonging to a different raid array. Change-Id: Id5f6c7e3ed7223f6a8fc7455f75831fbbcac7e43 Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
This commit is contained in:
parent
957acd43b9
commit
e61c1c51be
@ -225,12 +225,11 @@ raid_bdev_free_base_bdev_resource(struct raid_base_bdev_info *base_info)
|
||||
|
||||
assert(spdk_get_thread() == spdk_thread_get_app_thread());
|
||||
|
||||
if (base_info->bdev != NULL) {
|
||||
if (base_info->is_configured) {
|
||||
assert(base_info->desc);
|
||||
assert(raid_bdev->num_base_bdevs_discovered);
|
||||
raid_bdev->num_base_bdevs_discovered--;
|
||||
spdk_bdev_module_release_bdev(base_info->bdev);
|
||||
base_info->bdev = NULL;
|
||||
base_info->is_configured = false;
|
||||
}
|
||||
|
||||
if (base_info->app_thread_ch != NULL) {
|
||||
@ -238,6 +237,11 @@ raid_bdev_free_base_bdev_resource(struct raid_base_bdev_info *base_info)
|
||||
base_info->app_thread_ch = NULL;
|
||||
}
|
||||
|
||||
if (base_info->bdev != NULL) {
|
||||
spdk_bdev_module_release_bdev(base_info->bdev);
|
||||
base_info->bdev = NULL;
|
||||
}
|
||||
|
||||
if (base_info->desc != NULL) {
|
||||
spdk_bdev_close(base_info->desc);
|
||||
base_info->desc = NULL;
|
||||
@ -1812,6 +1816,48 @@ raid_bdev_delete(struct raid_bdev *raid_bdev, raid_bdev_destruct_cb cb_fn, void
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
raid_bdev_configure_base_bdev_cont(struct raid_base_bdev_info *base_info)
|
||||
{
|
||||
struct raid_bdev *raid_bdev = base_info->raid_bdev;
|
||||
int rc;
|
||||
|
||||
base_info->is_configured = true;
|
||||
|
||||
raid_bdev->num_base_bdevs_discovered++;
|
||||
assert(raid_bdev->num_base_bdevs_discovered <= raid_bdev->num_base_bdevs);
|
||||
|
||||
if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) {
|
||||
rc = raid_bdev_configure(raid_bdev);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to configure raid bdev: %s\n", spdk_strerror(-rc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
raid_bdev_configure_base_bdev_load_sb_cb(const struct raid_bdev_superblock *sb, int status,
|
||||
void *ctx)
|
||||
{
|
||||
struct raid_base_bdev_info *base_info = ctx;
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
/* valid superblock found */
|
||||
SPDK_ERRLOG("Existing raid superblock found on bdev %s\n", base_info->name);
|
||||
raid_bdev_free_base_bdev_resource(base_info);
|
||||
break;
|
||||
case -EINVAL:
|
||||
/* no valid superblock */
|
||||
raid_bdev_configure_base_bdev_cont(base_info);
|
||||
break;
|
||||
default:
|
||||
SPDK_ERRLOG("Failed to examine bdev %s: %s\n",
|
||||
base_info->name, spdk_strerror(-status));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
raid_bdev_configure_base_bdev(struct raid_base_bdev_info *base_info)
|
||||
{
|
||||
@ -1914,27 +1960,26 @@ raid_bdev_configure_base_bdev(struct raid_base_bdev_info *base_info)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (base_info->data_size == 0) {
|
||||
base_info->data_size = bdev->blockcnt - base_info->data_offset;
|
||||
} else if (base_info->data_offset + base_info->data_size > bdev->blockcnt) {
|
||||
SPDK_ERRLOG("Data offset and size exceeds base bdev capacity %lu on bdev '%s'\n",
|
||||
bdev->blockcnt, base_info->name);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
base_info->bdev = bdev;
|
||||
base_info->desc = desc;
|
||||
base_info->blockcnt = bdev->blockcnt;
|
||||
|
||||
raid_bdev->num_base_bdevs_discovered++;
|
||||
assert(raid_bdev->num_base_bdevs_discovered <= raid_bdev->num_base_bdevs);
|
||||
if (base_info->data_size == 0) {
|
||||
base_info->data_size = bdev->blockcnt - base_info->data_offset;
|
||||
|
||||
if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) {
|
||||
rc = raid_bdev_configure(raid_bdev);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to configure raid bdev: %s\n", spdk_strerror(-rc));
|
||||
/* check for existing superblock when using a new bdev */
|
||||
rc = raid_bdev_load_base_bdev_superblock(desc, base_info->app_thread_ch,
|
||||
raid_bdev_configure_base_bdev_load_sb_cb, base_info);
|
||||
if (rc) {
|
||||
SPDK_ERRLOG("Failed to read bdev %s superblock: %s\n",
|
||||
bdev->name, spdk_strerror(-rc));
|
||||
}
|
||||
} else if (base_info->data_offset + base_info->data_size > bdev->blockcnt) {
|
||||
SPDK_ERRLOG("Data offset and size exceeds base bdev capacity %lu on bdev '%s'\n",
|
||||
bdev->blockcnt, base_info->name);
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
raid_bdev_configure_base_bdev_cont(base_info);
|
||||
}
|
||||
out:
|
||||
if (rc != 0) {
|
||||
|
@ -87,6 +87,9 @@ struct raid_base_bdev_info {
|
||||
|
||||
/* io channel for the app thread */
|
||||
struct spdk_io_channel *app_thread_ch;
|
||||
|
||||
/* Set to true when base bdev has completed the configuration process */
|
||||
bool is_configured;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -378,6 +378,20 @@ function raid_superblock_test() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Try to create new RAID bdev from malloc bdevs
|
||||
# Should not reach online state due to superblock still present on base bdevs
|
||||
$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs_malloc[*]}" -n $raid_bdev_name
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop the RAID bdev
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[]')
|
||||
if [ -n "$raid_bdev" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Re-add first base bdev
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[0]} -p ${base_bdevs_pt[0]} -u ${base_bdevs_pt_uuid[0]}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user