diff --git a/include/spdk/blob.h b/include/spdk/blob.h index 2d1e93766..d863e3a77 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -206,7 +206,18 @@ uint64_t spdk_blob_get_num_pages(struct spdk_blob *blob); /* Return the number of clusters allocated to the blob */ uint64_t spdk_blob_get_num_clusters(struct spdk_blob *blob); -/* Create a new blob with initial size of 'sz' clusters. */ +struct spdk_blob_opts { + uint64_t num_clusters; +}; + +/* Initialize an spdk_blob_opts structure to the default blob option values. */ +void spdk_blob_opts_init(struct spdk_blob_opts *opts); + +/* Create a new blob with options. */ +void spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_opts *opts, + spdk_blob_op_with_id_complete cb_fn, void *cb_arg); + +/* Create a new blob. */ void spdk_bs_create_blob(struct spdk_blob_store *bs, spdk_blob_op_with_id_complete cb_fn, void *cb_arg); diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 053d27515..27843e081 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -83,6 +83,12 @@ _spdk_bs_release_cluster(struct spdk_blob_store *bs, uint32_t cluster_num) bs->num_free_clusters++; } +void +spdk_blob_opts_init(struct spdk_blob_opts *opts) +{ + opts->num_clusters = 0; +} + static struct spdk_blob_data * _spdk_blob_alloc(struct spdk_blob_store *bs, spdk_blob_id id) { @@ -2570,12 +2576,13 @@ _spdk_bs_create_blob_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) spdk_bs_sequence_finish(seq, bserrno); } -void spdk_bs_create_blob(struct spdk_blob_store *bs, - spdk_blob_op_with_id_complete cb_fn, void *cb_arg) +void spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_opts *opts, + spdk_blob_op_with_id_complete cb_fn, void *cb_arg) { struct spdk_blob_data *blob; uint32_t page_idx; struct spdk_bs_cpl cpl; + struct spdk_blob_opts opts_default; spdk_bs_sequence_t *seq; spdk_blob_id id; @@ -2596,6 +2603,12 @@ void spdk_bs_create_blob(struct spdk_blob_store *bs, return; } + if (!opts) { + spdk_blob_opts_init(&opts_default); + opts = &opts_default; + } + + spdk_blob_resize(__data_to_blob(blob), opts->num_clusters); cpl.type = SPDK_BS_CPL_TYPE_BLOBID; cpl.u.blobid.cb_fn = cb_fn; cpl.u.blobid.cb_arg = cb_arg; @@ -2611,6 +2624,12 @@ void spdk_bs_create_blob(struct spdk_blob_store *bs, _spdk_blob_persist(seq, blob, _spdk_bs_create_blob_cpl, blob); } +void spdk_bs_create_blob(struct spdk_blob_store *bs, + spdk_blob_op_with_id_complete cb_fn, void *cb_arg) +{ + spdk_bs_create_blob_ext(bs, NULL, cb_fn, cb_arg); +} + /* END spdk_bs_create_blob */ /* START spdk_blob_resize */ diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index be2292de5..573117a2d 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -265,6 +265,80 @@ blob_open(void) g_bs = NULL; } +static void +blob_create(void) +{ + struct spdk_blob_store *bs; + struct spdk_bs_dev *dev; + struct spdk_blob *blob; + struct spdk_blob_opts opts; + spdk_blob_id blobid; + + 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; + + /* Create blob with 10 clusters */ + + spdk_blob_opts_init(&opts); + opts.num_clusters = 10; + + 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); + 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; + CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10) + + spdk_blob_close(blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + /* Create blob with 0 clusters */ + + spdk_blob_opts_init(&opts); + opts.num_clusters = 0; + + 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); + 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; + CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0) + + spdk_blob_close(blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + /* Create blob with default options (opts == NULL) */ + + spdk_bs_create_blob_ext(bs, NULL, blob_op_with_id_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); + 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; + CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0) + + spdk_blob_close(blob, 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; +} static void blob_delete(void) { @@ -2173,6 +2247,7 @@ int main(int argc, char **argv) if ( CU_add_test(suite, "blob_init", blob_init) == NULL || CU_add_test(suite, "blob_open", blob_open) == NULL || + CU_add_test(suite, "blob_create", blob_create) == NULL || CU_add_test(suite, "blob_delete", blob_delete) == NULL || CU_add_test(suite, "blob_resize", blob_resize) == NULL || CU_add_test(suite, "channel_ops", channel_ops) == NULL ||