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());
|
assert(spdk_get_thread() == spdk_thread_get_app_thread());
|
||||||
|
|
||||||
if (base_info->bdev != NULL) {
|
if (base_info->is_configured) {
|
||||||
assert(base_info->desc);
|
assert(base_info->desc);
|
||||||
assert(raid_bdev->num_base_bdevs_discovered);
|
assert(raid_bdev->num_base_bdevs_discovered);
|
||||||
raid_bdev->num_base_bdevs_discovered--;
|
raid_bdev->num_base_bdevs_discovered--;
|
||||||
spdk_bdev_module_release_bdev(base_info->bdev);
|
base_info->is_configured = false;
|
||||||
base_info->bdev = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base_info->app_thread_ch != NULL) {
|
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;
|
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) {
|
if (base_info->desc != NULL) {
|
||||||
spdk_bdev_close(base_info->desc);
|
spdk_bdev_close(base_info->desc);
|
||||||
base_info->desc = NULL;
|
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
|
static int
|
||||||
raid_bdev_configure_base_bdev(struct raid_base_bdev_info *base_info)
|
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;
|
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->bdev = bdev;
|
||||||
base_info->desc = desc;
|
base_info->desc = desc;
|
||||||
base_info->blockcnt = bdev->blockcnt;
|
base_info->blockcnt = bdev->blockcnt;
|
||||||
|
|
||||||
raid_bdev->num_base_bdevs_discovered++;
|
if (base_info->data_size == 0) {
|
||||||
assert(raid_bdev->num_base_bdevs_discovered <= raid_bdev->num_base_bdevs);
|
base_info->data_size = bdev->blockcnt - base_info->data_offset;
|
||||||
|
|
||||||
if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) {
|
/* check for existing superblock when using a new bdev */
|
||||||
rc = raid_bdev_configure(raid_bdev);
|
rc = raid_bdev_load_base_bdev_superblock(desc, base_info->app_thread_ch,
|
||||||
if (rc != 0) {
|
raid_bdev_configure_base_bdev_load_sb_cb, base_info);
|
||||||
SPDK_ERRLOG("Failed to configure raid bdev: %s\n", spdk_strerror(-rc));
|
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:
|
out:
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
@ -87,6 +87,9 @@ struct raid_base_bdev_info {
|
|||||||
|
|
||||||
/* io channel for the app thread */
|
/* io channel for the app thread */
|
||||||
struct spdk_io_channel *app_thread_ch;
|
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
|
return 1
|
||||||
fi
|
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
|
# 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]}
|
$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