blob: pass bs context with esnap_bs_dev_create
When a blobstore consumer creates or loads a blobstore, it should be able to set a per-blobstore context pointer that will be passed back to the consumer via bs->esnap_bs_dev_create(). Signed-off-by: Mike Gerdts <mgerdts@nvidia.com> Change-Id: I59c0ebe21eaf65c3d79a4ac3469715283f56313a Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14970 Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
184325fd2b
commit
a4a73fec9c
@ -132,6 +132,8 @@ typedef void (*spdk_blob_op_with_bs_dev)(void *cb_arg, struct spdk_bs_dev *bs_de
|
||||
* callback registered with the blobstore to create the external snapshot device. The blobstore
|
||||
* consumer must set this while loading the blobstore if it intends to support external snapshots.
|
||||
*
|
||||
* \param bs_ctx Context provided by the blobstore consumer via esnap_ctx member of struct
|
||||
* spdk_bs_opts.
|
||||
* \param blob The blob that needs its external snapshot device.
|
||||
* \param esnap_id A copy of the esnap_id passed via blob_opts when creating the esnap clone.
|
||||
* \param id_size The size in bytes of the data referenced by esnap_id.
|
||||
@ -139,8 +141,9 @@ typedef void (*spdk_blob_op_with_bs_dev)(void *cb_arg, struct spdk_bs_dev *bs_de
|
||||
*
|
||||
* \return 0 on success, else a negative errno.
|
||||
*/
|
||||
typedef int (*spdk_bs_esnap_dev_create)(struct spdk_blob *blob, const void *esnap_id,
|
||||
uint32_t id_size, struct spdk_bs_dev **bs_dev);
|
||||
typedef int (*spdk_bs_esnap_dev_create)(void *bs_ctx, struct spdk_blob *blob,
|
||||
const void *esnap_id, uint32_t id_size,
|
||||
struct spdk_bs_dev **bs_dev);
|
||||
|
||||
struct spdk_bs_dev_cb_args {
|
||||
spdk_bs_dev_cpl cb_fn;
|
||||
@ -287,8 +290,13 @@ struct spdk_bs_opts {
|
||||
* External snapshot creation callback to register with the blobstore.
|
||||
*/
|
||||
spdk_bs_esnap_dev_create esnap_bs_dev_create;
|
||||
|
||||
/**
|
||||
* Context to pass with esnap_bs_dev_create.
|
||||
*/
|
||||
void *esnap_ctx;
|
||||
} __attribute__((packed));
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_opts) == 80, "Incorrect size");
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_opts) == 88, "Incorrect size");
|
||||
|
||||
/**
|
||||
* Initialize a spdk_bs_opts structure to the default blobstore option values.
|
||||
|
@ -1370,7 +1370,7 @@ blob_load_esnap(struct spdk_blob *blob)
|
||||
|
||||
SPDK_INFOLOG(blob, "Creating external snapshot device\n");
|
||||
|
||||
rc = bs->esnap_bs_dev_create(blob, esnap_id, (uint32_t)id_len, &bs_dev);
|
||||
rc = bs->esnap_bs_dev_create(bs->esnap_ctx, blob, esnap_id, (uint32_t)id_len, &bs_dev);
|
||||
if (rc != 0) {
|
||||
SPDK_DEBUGLOG(blob_esnap, "blob 0x%" PRIx64 ": failed to load back_bs_dev "
|
||||
"with error %d\n", blob->id, rc);
|
||||
@ -3471,6 +3471,7 @@ spdk_bs_opts_init(struct spdk_bs_opts *opts, size_t opts_size)
|
||||
SET_FIELD(iter_cb_arg, NULL);
|
||||
SET_FIELD(force_recover, false);
|
||||
SET_FIELD(esnap_bs_dev_create, NULL);
|
||||
SET_FIELD(esnap_ctx, NULL);
|
||||
|
||||
#undef FIELD_OK
|
||||
#undef SET_FIELD
|
||||
@ -3599,6 +3600,7 @@ bs_alloc(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts, struct spdk_blob_st
|
||||
bs->super_blob = SPDK_BLOBID_INVALID;
|
||||
memcpy(&bs->bstype, &opts->bstype, sizeof(opts->bstype));
|
||||
bs->esnap_bs_dev_create = opts->esnap_bs_dev_create;
|
||||
bs->esnap_ctx = opts->esnap_ctx;
|
||||
|
||||
/* The metadata is assumed to be at least 1 page */
|
||||
bs->used_md_pages = spdk_bit_array_create(1);
|
||||
@ -4676,12 +4678,13 @@ bs_opts_copy(struct spdk_bs_opts *src, struct spdk_bs_opts *dst)
|
||||
SET_FIELD(iter_cb_arg);
|
||||
SET_FIELD(force_recover);
|
||||
SET_FIELD(esnap_bs_dev_create);
|
||||
SET_FIELD(esnap_ctx);
|
||||
|
||||
dst->opts_size = src->opts_size;
|
||||
|
||||
/* 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_bs_opts) == 80, "Incorrect size");
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_opts) == 88, "Incorrect size");
|
||||
|
||||
#undef FIELD_OK
|
||||
#undef SET_FIELD
|
||||
|
@ -188,6 +188,7 @@ struct spdk_blob_store {
|
||||
bool clean;
|
||||
|
||||
spdk_bs_esnap_dev_create esnap_bs_dev_create;
|
||||
void *esnap_ctx;
|
||||
};
|
||||
|
||||
struct spdk_bs_channel {
|
||||
|
@ -7421,6 +7421,7 @@ blob_esnap_create(void)
|
||||
uint64_t esnap_num_blocks;
|
||||
uint32_t sz;
|
||||
spdk_blob_id blobid;
|
||||
uint32_t bs_ctx_count;
|
||||
|
||||
cluster_sz = spdk_bs_get_cluster_size(bs);
|
||||
block_sz = spdk_bs_get_io_unit_size(bs);
|
||||
@ -7498,6 +7499,29 @@ blob_esnap_create(void)
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno != 0);
|
||||
CU_ASSERT(g_blob == NULL);
|
||||
|
||||
/* Reload the blobstore with ctx set and verify it is passed to the esnap create callback */
|
||||
bs_ctx_count = 0;
|
||||
spdk_bs_opts_init(&bs_opts, sizeof(bs_opts));
|
||||
bs_opts.esnap_bs_dev_create = ut_esnap_create_with_count;
|
||||
bs_opts.esnap_ctx = &bs_ctx_count;
|
||||
ut_bs_reload(&bs, &bs_opts);
|
||||
/* Loading the blobstore triggers the esnap to be loaded */
|
||||
CU_ASSERT(bs_ctx_count == 1);
|
||||
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(g_blob != NULL);
|
||||
/* Opening the blob also triggers the esnap to be loaded */
|
||||
CU_ASSERT(bs_ctx_count == 2);
|
||||
blob = g_blob;
|
||||
SPDK_CU_ASSERT_FATAL(blob_is_esnap_clone(blob));
|
||||
sz = spdk_blob_get_num_clusters(blob);
|
||||
CU_ASSERT(sz == esnap_num_clusters + 1);
|
||||
spdk_blob_close(blob, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
g_blob = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -92,11 +92,14 @@ ut_esnap_dev_alloc(const struct ut_esnap_opts *opts)
|
||||
}
|
||||
|
||||
static int
|
||||
ut_esnap_create(struct spdk_blob *blob, const void *id, uint32_t id_len,
|
||||
ut_esnap_create(void *bs_ctx, struct spdk_blob *blob, const void *id, uint32_t id_len,
|
||||
struct spdk_bs_dev **bs_devp)
|
||||
{
|
||||
struct spdk_bs_dev *bs_dev = NULL;
|
||||
|
||||
/* With any blobstore that will use bs_ctx, wrap this function and pass NULL as bs_ctx. */
|
||||
CU_ASSERT(bs_ctx == NULL);
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(id != NULL);
|
||||
SPDK_CU_ASSERT_FATAL(sizeof(struct ut_esnap_opts) == id_len);
|
||||
|
||||
@ -106,3 +109,15 @@ ut_esnap_create(struct spdk_blob *blob, const void *id, uint32_t id_len,
|
||||
*bs_devp = bs_dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ut_esnap_create_with_count(void *bs_ctx, struct spdk_blob *blob,
|
||||
const void *id, uint32_t id_len, struct spdk_bs_dev **bs_devp)
|
||||
{
|
||||
uint32_t *bs_ctx_count = bs_ctx;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(bs_ctx != NULL);
|
||||
|
||||
(*bs_ctx_count)++;
|
||||
return ut_esnap_create(NULL, blob, id, id_len, bs_devp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user