bdev_part: allow UUID to be specified

This introduces spdk_bdev_part_construct_ext(), which takes an options
structure as an optional parameter. The options structure has one
option: uuid.

Signed-off-by: Mike Gerdts <mgerdts@nvidia.com>
Change-Id: I5e9fdc8e88b78b303e60a0e721d7a74854ac37a9
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/17835
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Mike Gerdts 2023-04-27 15:10:28 -05:00 committed by David Ko
parent 51d7df517c
commit 9b687d7753
5 changed files with 156 additions and 3 deletions

View File

@ -53,6 +53,10 @@ receive and send the I/O management commands.
New `spdk_nvmf_transport_create_async` was added, it accepts a callback and callback argument.
`spdk_nvmf_transport_create` is marked deprecated.
### part
New API `spdk_bdev_part_construct_ext` is added and allows the bdev's UUID to be specified.
### examples
`examples/nvme/perf` application now accepts `--use-every-core` parameter that changes

View File

@ -1463,6 +1463,24 @@ int spdk_bdev_part_base_construct_ext(const char *bdev_name,
spdk_io_channel_destroy_cb ch_destroy_cb,
struct spdk_bdev_part_base **base);
/** Options used when constructing a part bdev. */
struct spdk_bdev_part_construct_opts {
/* Size of this structure in bytes */
uint64_t opts_size;
/** UUID of the bdev */
struct spdk_uuid uuid;
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_part_construct_opts) == 24, "Incorrect size");
/**
* Initialize options that will be passed to spdk_bdev_part_construct_ext().
*
* \param opts Options structure to initialize
* \param size Size of opts structure.
*/
void spdk_bdev_part_construct_opts_init(struct spdk_bdev_part_construct_opts *opts, uint64_t size);
/**
* Create a logical spdk_bdev_part on top of a base.
*
@ -1480,6 +1498,25 @@ int spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_
char *name, uint64_t offset_blocks, uint64_t num_blocks,
char *product_name);
/**
* Create a logical spdk_bdev_part on top of a base with a non-NULL bdev UUID
*
* \param part The part object allocated by the user.
* \param base The base from which to create the part.
* \param name The name of the new spdk_bdev_part.
* \param offset_blocks The offset into the base bdev at which this part begins.
* \param num_blocks The number of blocks that this part will span.
* \param product_name Unique name for this type of block device.
* \param opts Additional options.
*
* \return 0 on success.
* \return -1 if the bases underlying bdev cannot be claimed by the current module.
*/
int spdk_bdev_part_construct_ext(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
char *name, uint64_t offset_blocks, uint64_t num_blocks,
char *product_name,
const struct spdk_bdev_part_construct_opts *opts);
/**
* Forwards I/O from an spdk_bdev_part to the underlying base bdev.
*

View File

@ -497,13 +497,68 @@ spdk_bdev_part_base_construct_ext(const char *bdev_name,
return 0;
}
void
spdk_bdev_part_construct_opts_init(struct spdk_bdev_part_construct_opts *opts, uint64_t size)
{
if (opts == NULL) {
SPDK_ERRLOG("opts should not be NULL\n");
assert(opts != NULL);
return;
}
if (size == 0) {
SPDK_ERRLOG("size should not be zero\n");
assert(size != 0);
return;
}
memset(opts, 0, size);
opts->opts_size = size;
}
static void
part_construct_opts_copy(const struct spdk_bdev_part_construct_opts *src,
struct spdk_bdev_part_construct_opts *dst)
{
if (src->opts_size == 0) {
SPDK_ERRLOG("size should not be zero\n");
assert(false);
}
memset(dst, 0, sizeof(*dst));
dst->opts_size = src->opts_size;
#define FIELD_OK(field) \
offsetof(struct spdk_bdev_part_construct_opts, field) + sizeof(src->field) <= src->opts_size
#define SET_FIELD(field) \
if (FIELD_OK(field)) { \
dst->field = src->field; \
} \
SET_FIELD(uuid);
/* You should not remove this statement, but need to update the assert statement
* if you add a new field, and also add a corresponding SET_FIELD statement */
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_part_construct_opts) == 24, "Incorrect size");
#undef FIELD_OK
#undef SET_FIELD
}
int
spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
spdk_bdev_part_construct_ext(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
char *name, uint64_t offset_blocks, uint64_t num_blocks,
char *product_name)
char *product_name, const struct spdk_bdev_part_construct_opts *_opts)
{
int rc;
bool first_claimed = false;
struct spdk_bdev_part_construct_opts opts;
if (_opts == NULL) {
spdk_bdev_part_construct_opts_init(&opts, sizeof(opts));
} else {
part_construct_opts_copy(_opts, &opts);
}
part->internal.bdev.blocklen = base->bdev->blocklen;
part->internal.bdev.blockcnt = num_blocks;
@ -535,6 +590,8 @@ spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base
return -1;
}
spdk_uuid_copy(&part->internal.bdev.uuid, &opts.uuid);
base->ref++;
part->internal.base = base;
@ -575,3 +632,12 @@ spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base
return rc;
}
int
spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
char *name, uint64_t offset_blocks, uint64_t num_blocks,
char *product_name)
{
return spdk_bdev_part_construct_ext(part, base, name, offset_blocks, num_blocks,
product_name, NULL);
}

View File

@ -152,7 +152,9 @@
spdk_bdev_part_free;
spdk_bdev_part_base_hotremove;
spdk_bdev_part_base_construct_ext;
spdk_bdev_part_construct_opts_init;
spdk_bdev_part_construct;
spdk_bdev_part_construct_ext;
spdk_bdev_part_submit_request;
spdk_bdev_part_submit_request_ext;
spdk_bdev_part_get_bdev;

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2018 Intel Corporation.
* All rights reserved.
* Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include "spdk_cunit.h"
@ -393,6 +394,48 @@ part_get_io_channel_test(void)
ut_fini_bdev();
}
static void
part_construct_ext(void)
{
struct spdk_bdev_part_base *base;
struct spdk_bdev_part part1 = {};
struct spdk_bdev bdev_base = {};
SPDK_BDEV_PART_TAILQ tailq = TAILQ_HEAD_INITIALIZER(tailq);
const char *uuid = "7ed764b7-a841-41b1-ba93-6548d9335a44";
struct spdk_bdev_part_construct_opts opts;
int rc;
bdev_base.name = "base";
bdev_base.fn_table = &base_fn_table;
bdev_base.module = &bdev_ut_if;
rc = spdk_bdev_register(&bdev_base);
CU_ASSERT(rc == 0);
rc = spdk_bdev_part_base_construct_ext("base", NULL, &vbdev_ut_if,
&part_fn_table, &tailq, NULL,
NULL, 0, NULL, NULL, &base);
CU_ASSERT(rc == 0);
SPDK_CU_ASSERT_FATAL(base != NULL);
/* Verify opts.uuid is used as bdev UUID */
spdk_bdev_part_construct_opts_init(&opts, sizeof(opts));
spdk_uuid_parse(&opts.uuid, uuid);
rc = spdk_bdev_part_construct_ext(&part1, base, "test1", 0, 100, "test", &opts);
SPDK_CU_ASSERT_FATAL(rc == 0);
SPDK_CU_ASSERT_FATAL(base->ref == 1);
SPDK_CU_ASSERT_FATAL(base->claimed == true);
CU_ASSERT(spdk_bdev_get_by_name(uuid) != NULL);
CU_ASSERT(spdk_bdev_get_by_name("test1") != NULL);
/* Clean up */
spdk_bdev_part_base_hotremove(base, &tailq);
spdk_bdev_part_base_free(base);
_part_cleanup(&part1);
spdk_bdev_unregister(&bdev_base, NULL, NULL);
poll_threads();
}
int
main(int argc, char **argv)
{
@ -407,6 +450,7 @@ main(int argc, char **argv)
CU_ADD_TEST(suite, part_test);
CU_ADD_TEST(suite, part_free_test);
CU_ADD_TEST(suite, part_get_io_channel_test);
CU_ADD_TEST(suite, part_construct_ext);
allocate_cores(1);
allocate_threads(1);