diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 943e2e9cd..1b77bcfe3 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -50,6 +50,8 @@ static int spdk_bs_register_md_thread(struct spdk_blob_store *bs); static int spdk_bs_unregister_md_thread(struct spdk_blob_store *bs); static void _spdk_blob_close_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno); +void _spdk_blob_insert_cluster_on_md_thread(struct spdk_blob_data *blob, uint32_t cluster_num, + uint64_t cluster, spdk_blob_op_complete cb_fn, void *cb_arg); static inline size_t divide_round_up(size_t num, size_t divisor) @@ -3214,6 +3216,71 @@ spdk_blob_sync_md(struct spdk_blob *_blob, spdk_blob_op_complete cb_fn, void *cb /* END spdk_blob_sync_md */ +struct spdk_blob_insert_cluster_ctx { + struct spdk_thread *thread; + struct spdk_blob_data *blob; + uint32_t cluster_num; /* cluster index in blob */ + uint32_t cluster; /* cluster on disk */ + int rc; + spdk_blob_op_complete cb_fn; + void *cb_arg; +}; + +static void +_spdk_blob_insert_cluster_msg_cpl(void *arg) +{ + struct spdk_blob_insert_cluster_ctx *ctx = arg; + + ctx->cb_fn(ctx->cb_arg, ctx->rc); + free(ctx); +} + +static void +_spdk_blob_insert_cluster_msg_cb(void *arg, int bserrno) +{ + struct spdk_blob_insert_cluster_ctx *ctx = arg; + + ctx->rc = bserrno; + spdk_thread_send_msg(ctx->thread, _spdk_blob_insert_cluster_msg_cpl, ctx); +} + +static void +_spdk_blob_insert_cluster_msg(void *arg) +{ + struct spdk_blob_insert_cluster_ctx *ctx = arg; + + ctx->rc = _spdk_blob_insert_cluster(ctx->blob, ctx->cluster_num, ctx->cluster); + if (ctx->rc != 0) { + spdk_thread_send_msg(ctx->thread, _spdk_blob_insert_cluster_msg_cpl, ctx); + return; + } + + ctx->blob->state = SPDK_BLOB_STATE_DIRTY; + _spdk_blob_sync_md(ctx->blob, _spdk_blob_insert_cluster_msg_cb, ctx); +} + +void +_spdk_blob_insert_cluster_on_md_thread(struct spdk_blob_data *blob, uint32_t cluster_num, + uint64_t cluster, spdk_blob_op_complete cb_fn, void *cb_arg) +{ + struct spdk_blob_insert_cluster_ctx *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + cb_fn(cb_arg, -ENOMEM); + return; + } + + ctx->thread = spdk_get_thread(); + ctx->blob = blob; + ctx->cluster_num = cluster_num; + ctx->cluster = cluster; + ctx->cb_fn = cb_fn; + ctx->cb_arg = cb_arg; + + spdk_thread_send_msg(blob->bs->md_thread, _spdk_blob_insert_cluster_msg, ctx); +} + /* START spdk_blob_close */ static void diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 75b824283..f052b0a95 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -2679,7 +2679,7 @@ blob_thin_prov_alloc(void) spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); - CU_ASSERT(g_blob != NULL); + SPDK_CU_ASSERT_FATAL(g_blob != NULL); blob = g_blob; blob_data = __blob_to_data(blob); @@ -2698,6 +2698,88 @@ blob_thin_prov_alloc(void) g_bs = NULL; } +static void +blob_insert_cluster_msg(void) +{ + struct spdk_blob_store *bs; + struct spdk_bs_dev *dev; + struct spdk_blob *blob; + struct spdk_blob_data *blob_data; + struct spdk_blob_opts opts; + spdk_blob_id blobid; + uint64_t free_clusters; + + dev = init_dev(); + + spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + bs = g_bs; + free_clusters = spdk_bs_free_cluster_count(bs); + + /* Set blob as thin provisioned */ + spdk_blob_opts_init(&opts); + opts.thin_provision = true; + opts.num_clusters = 4; + + spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); + CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); + blobid = g_blobid; + + spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_blob != NULL); + blob = g_blob; + blob_data = __blob_to_data(blob); + + CU_ASSERT(blob_data->active.num_clusters == 4); + CU_ASSERT(spdk_blob_get_num_clusters(blob) == 4); + CU_ASSERT(blob_data->active.clusters[1] == 0); + + _spdk_bs_claim_cluster(bs, 0xF); + _spdk_blob_insert_cluster_on_md_thread(blob_data, 1, 0xF, blob_op_complete, NULL); + + CU_ASSERT(blob_data->active.clusters[1] != 0); + + spdk_blob_close(blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + /* Unload the blob store */ + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + g_blob = NULL; + g_blobid = 0; + + /* Load an existing blob store */ + dev = init_dev(); + spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + bs = g_bs; + + spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blob != NULL); + blob = g_blob; + blob_data = __blob_to_data(blob); + + CU_ASSERT(blob_data->active.clusters[1] != 0); + + spdk_blob_close(blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -2746,7 +2828,8 @@ int main(int argc, char **argv) CU_add_test(suite, "blob_flags", blob_flags) == NULL || CU_add_test(suite, "bs_version", bs_version) == NULL || CU_add_test(suite, "blob_set_xattrs", blob_set_xattrs) == NULL || - CU_add_test(suite, "blob_thin_prov_alloc", blob_thin_prov_alloc) == NULL + CU_add_test(suite, "blob_thin_prov_alloc", blob_thin_prov_alloc) == NULL || + CU_add_test(suite, "blob_insert_cluster_msg", blob_insert_cluster_msg) == NULL ) { CU_cleanup_registry(); return CU_get_error();