diff --git a/include/spdk/blob.h b/include/spdk/blob.h index 1cd1288c4f..21f4961b5f 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -208,6 +208,7 @@ uint64_t spdk_blob_get_num_clusters(struct spdk_blob *blob); struct spdk_blob_opts { uint64_t num_clusters; + bool thin_provision; /* Number of attributes */ size_t xattr_count; /* Array of attribute names. Caller should free this array after use. */ diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 8dcc85525b..1749d43699 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -87,6 +87,7 @@ void spdk_blob_opts_init(struct spdk_blob_opts *opts) { opts->num_clusters = 0; + opts->thin_provision = false; opts->xattr_count = 0; opts->xattr_names = NULL; opts->xattr_ctx = NULL; @@ -2735,6 +2736,13 @@ _spdk_blob_set_xattrs(struct spdk_blob *blob, const struct spdk_blob_opts *opts) return 0; } +static void +_spdk_blob_set_thin_provision(struct spdk_blob_data *blob) +{ + blob->invalid_flags |= SPDK_BLOB_THIN_PROV; + blob->state = SPDK_BLOB_STATE_DIRTY; +} + 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) { @@ -2774,6 +2782,9 @@ void spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_ cb_fn(cb_arg, 0, rc); return; } + if (opts->thin_provision) { + _spdk_blob_set_thin_provision(blob); + } spdk_blob_resize(__data_to_blob(blob), opts->num_clusters); cpl.type = SPDK_BS_CPL_TYPE_BLOBID; cpl.u.blobid.cb_fn = cb_fn; diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index 7e7578f565..f650436766 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -235,11 +235,8 @@ struct spdk_blob_md_descriptor_extent { } extents[0]; }; -/* - * As new flags are defined, these values will be updated to reflect the - * mask of all flag values understood by this application. - */ -#define SPDK_BLOB_INVALID_FLAGS_MASK 0 +#define SPDK_BLOB_THIN_PROV (1ULL << 0) +#define SPDK_BLOB_INVALID_FLAGS_MASK SPDK_BLOB_THIN_PROV #define SPDK_BLOB_READ_ONLY (1ULL << 0) #define SPDK_BLOB_DATA_RO_FLAGS_MASK SPDK_BLOB_READ_ONLY diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index de783ebced..fe61853b4b 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -343,6 +343,75 @@ blob_create(void) g_bs = NULL; } + +static void +blob_thin_provision(void) +{ + struct spdk_blob_store *bs; + struct spdk_bs_dev *dev; + struct spdk_blob *blob; + struct spdk_blob_opts opts; + struct spdk_bs_opts bs_opts; + spdk_blob_id blobid; + + dev = init_dev(); + spdk_bs_opts_init(&bs_opts); + strncpy(bs_opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); + + /* Initialize a new blob store */ + spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + bs = g_bs; + + /* Create blob with thin provisioning enabled */ + + spdk_blob_opts_init(&opts); + opts.thin_provision = true; + 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(__blob_to_data(blob)->invalid_flags & SPDK_BLOB_THIN_PROV); + + 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; + + /* Load an existing blob store and check if invalid_flags is set */ + dev = init_dev(); + strncpy(bs_opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &bs_opts, 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(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(__blob_to_data(blob)->invalid_flags & SPDK_BLOB_THIN_PROV); + + 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) { @@ -2483,6 +2552,7 @@ int main(int argc, char **argv) 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_thin_provision", blob_thin_provision) == NULL || CU_add_test(suite, "blob_delete", blob_delete) == NULL || CU_add_test(suite, "blob_resize", blob_resize) == NULL || CU_add_test(suite, "blob_read_only", blob_read_only) == NULL ||