From 4d5ee263b1c24cd52eb997335e08602ae1a06f24 Mon Sep 17 00:00:00 2001 From: Mike Gerdts Date: Tue, 11 Oct 2022 08:52:13 -0500 Subject: [PATCH] blob: pass blob context to esnap_bs_dev_create When consumers open a blob with spdk_bs_open_blob_ext(), they can set esnap_ctx in struct spdk_blob_open_opts to have that context passed to bs->external_bs_dev_create(). Change-Id: I0c1a9cec0e5aed5ef2a7143103e822cbe400aabb Signed-off-by: Mike Gerdts Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14971 Reviewed-by: Jim Harris Community-CI: Mellanox Build Bot Reviewed-by: Ben Walker Tested-by: SPDK CI Jenkins --- include/spdk/blob.h | 12 ++++++++++-- lib/blob/blobstore.c | 17 ++++++++++------- lib/blob/request.h | 3 ++- test/unit/lib/blob/blob.c/blob_ut.c | 16 +++++++++++++++- test/unit/lib/blob/blob.c/esnap_dev.c | 23 ++++++++++++++++++----- 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/include/spdk/blob.h b/include/spdk/blob.h index d3f21e5f8..49a150ff6 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -134,6 +134,8 @@ typedef void (*spdk_blob_op_with_bs_dev)(void *cb_arg, struct spdk_bs_dev *bs_de * * \param bs_ctx Context provided by the blobstore consumer via esnap_ctx member of struct * spdk_bs_opts. + * \param blob_ctx Context provided to spdk_bs_open_ext() via esnap_ctx member of struct + * spdk_bs_open_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. @@ -141,7 +143,7 @@ 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)(void *bs_ctx, struct spdk_blob *blob, +typedef int (*spdk_bs_esnap_dev_create)(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob, const void *esnap_id, uint32_t id_size, struct spdk_bs_dev **bs_dev); @@ -753,8 +755,14 @@ struct spdk_blob_open_opts { * New added fields should be put at the end of the struct. */ size_t opts_size; + + /** + * Blob context to be passed to any call of bs->external_bs_dev_create() that is triggered + * by this open call. + */ + void *esnap_ctx; }; -SPDK_STATIC_ASSERT(sizeof(struct spdk_blob_open_opts) == 16, "Incorrect size"); +SPDK_STATIC_ASSERT(sizeof(struct spdk_blob_open_opts) == 24, "Incorrect size"); /** * Initialize a spdk_blob_open_opts structure to the default blob option values. diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index b8b349c2a..35f7e581e 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -1340,7 +1340,7 @@ blob_load_snapshot_cpl(void *cb_arg, struct spdk_blob *snapshot, int bserrno) static void blob_update_clear_method(struct spdk_blob *blob); static int -blob_load_esnap(struct spdk_blob *blob) +blob_load_esnap(struct spdk_blob *blob, void *blob_ctx) { struct spdk_blob_store *bs = blob->bs; struct spdk_bs_dev *bs_dev = NULL; @@ -1364,7 +1364,8 @@ blob_load_esnap(struct spdk_blob *blob) SPDK_INFOLOG(blob, "Creating external snapshot device\n"); - rc = bs->esnap_bs_dev_create(bs->esnap_ctx, blob, esnap_id, (uint32_t)id_len, &bs_dev); + rc = bs->esnap_bs_dev_create(bs->esnap_ctx, blob_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); @@ -1388,7 +1389,7 @@ blob_load_esnap(struct spdk_blob *blob) } static void -blob_load_backing_dev(void *cb_arg) +blob_load_backing_dev(spdk_bs_sequence_t *seq, void *cb_arg) { struct spdk_blob_load_ctx *ctx = cb_arg; struct spdk_blob *blob = ctx->blob; @@ -1397,7 +1398,7 @@ blob_load_backing_dev(void *cb_arg) int rc; if (blob_is_esnap_clone(blob)) { - rc = blob_load_esnap(blob); + rc = blob_load_esnap(blob, seq->cpl.u.blob_handle.esnap_ctx); assert((rc == 0) ^ (blob->back_bs_dev == NULL)); blob_load_final(ctx, rc); return; @@ -1507,7 +1508,7 @@ blob_load_cpl_extents_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) } } - blob_load_backing_dev(ctx); + blob_load_backing_dev(seq, ctx); } static void @@ -1595,7 +1596,7 @@ blob_load_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) if (blob->extent_table_found) { blob_load_cpl_extents_cpl(seq, ctx, 0); } else { - blob_load_backing_dev(ctx); + blob_load_backing_dev(seq, ctx); } } @@ -7418,12 +7419,13 @@ blob_open_opts_copy(const struct spdk_blob_open_opts *src, struct spdk_blob_open } \ SET_FIELD(clear_method); + 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_blob_open_opts) == 16, "Incorrect size"); + SPDK_STATIC_ASSERT(sizeof(struct spdk_blob_open_opts) == 24, "Incorrect size"); #undef FIELD_OK #undef SET_FIELD @@ -7476,6 +7478,7 @@ bs_open_blob(struct spdk_blob_store *bs, cpl.u.blob_handle.cb_fn = cb_fn; cpl.u.blob_handle.cb_arg = cb_arg; cpl.u.blob_handle.blob = blob; + cpl.u.blob_handle.esnap_ctx = opts_local.esnap_ctx; seq = bs_sequence_start(bs->md_channel, &cpl); if (!seq) { diff --git a/lib/blob/request.h b/lib/blob/request.h index 54112824e..63ad98209 100644 --- a/lib/blob/request.h +++ b/lib/blob/request.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (C) 2017 Intel Corporation. * All rights reserved. - * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #ifndef SPDK_BS_REQUEST_H @@ -65,6 +65,7 @@ struct spdk_bs_cpl { spdk_blob_op_with_handle_complete cb_fn; void *cb_arg; struct spdk_blob *blob; + void *esnap_ctx; } blob_handle; struct { diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 30315c056..6f8368c37 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -7415,13 +7415,14 @@ blob_esnap_create(void) struct spdk_bs_opts bs_opts; struct ut_esnap_opts esnap_opts; struct spdk_blob_opts opts; + struct spdk_blob_open_opts open_opts; struct spdk_blob *blob; uint32_t cluster_sz, block_sz; const uint32_t esnap_num_clusters = 4; uint64_t esnap_num_blocks; uint32_t sz; spdk_blob_id blobid; - uint32_t bs_ctx_count; + uint32_t bs_ctx_count, blob_ctx_count; cluster_sz = spdk_bs_get_cluster_size(bs); block_sz = spdk_bs_get_io_unit_size(bs); @@ -7522,6 +7523,19 @@ blob_esnap_create(void) poll_threads(); CU_ASSERT(g_bserrno == 0); g_blob = NULL; + /* If open_opts.esnap_ctx is set it is passed to the esnap create callback */ + blob_ctx_count = 0; + spdk_blob_open_opts_init(&open_opts, sizeof(open_opts)); + open_opts.esnap_ctx = &blob_ctx_count; + spdk_bs_open_blob_ext(bs, blobid, &open_opts, blob_op_with_handle_complete, NULL); + poll_threads(); + blob = g_blob; + CU_ASSERT(bs_ctx_count == 3); + CU_ASSERT(blob_ctx_count == 1); + spdk_blob_close(blob, blob_op_complete, NULL); + poll_threads(); + CU_ASSERT(g_bserrno == 0); + g_blob = NULL; } static void diff --git a/test/unit/lib/blob/blob.c/esnap_dev.c b/test/unit/lib/blob/blob.c/esnap_dev.c index 355edc604..bb66d43f4 100644 --- a/test/unit/lib/blob/blob.c/esnap_dev.c +++ b/test/unit/lib/blob/blob.c/esnap_dev.c @@ -92,12 +92,14 @@ ut_esnap_dev_alloc(const struct ut_esnap_opts *opts) } static int -ut_esnap_create(void *bs_ctx, struct spdk_blob *blob, const void *id, uint32_t id_len, - struct spdk_bs_dev **bs_devp) +ut_esnap_create(void *bs_ctx, void *blob_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. */ + /* With any blobstore that will use bs_ctx or blob_ctx, wrap this function and pass NULL as + * bs_ctx and blob_ctx. */ + CU_ASSERT(bs_ctx == NULL); CU_ASSERT(bs_ctx == NULL); SPDK_CU_ASSERT_FATAL(id != NULL); @@ -111,13 +113,24 @@ ut_esnap_create(void *bs_ctx, struct spdk_blob *blob, const void *id, uint32_t i } static int -ut_esnap_create_with_count(void *bs_ctx, struct spdk_blob *blob, +ut_esnap_create_with_count(void *bs_ctx, void *blob_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; + uint32_t *blob_ctx_count = blob_ctx; SPDK_CU_ASSERT_FATAL(bs_ctx != NULL); (*bs_ctx_count)++; - return ut_esnap_create(NULL, blob, id, id_len, bs_devp); + + /* + * blob_ctx can be non-NULL when spdk_bs_open_blob() is used. Opens that come via + * spdk_bs_load(), spdk_bs_open_blob(), and those that come via spdk_bs_open_blob_ext() with + * NULL opts->esnap_ctx will have blob_ctx == NULL. + */ + if (blob_ctx_count != NULL) { + (*blob_ctx_count)++; + } + + return ut_esnap_create(NULL, NULL, blob, id, id_len, bs_devp); }