diff --git a/include/spdk/blob.h b/include/spdk/blob.h index b29895387..1cd1288c4 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -244,6 +244,9 @@ void spdk_bs_open_blob(struct spdk_blob_store *bs, spdk_blob_id blobid, * spdk_blob_sync_md() is called. */ int spdk_blob_resize(struct spdk_blob *blob, size_t sz); +/* Set blob as read only */ +void spdk_blob_set_read_only(struct spdk_blob *blob); + /* Sync a blob */ /* Make a blob persistent. This applies to resize, set xattr, * and remove xattr. These operations will not be persistent until diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 2fc2b0e40..196dbba28 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -227,6 +227,11 @@ _spdk_blob_parse_page(const struct spdk_blob_md_page *page, struct spdk_blob_dat blob->md_ro = true; } + if ((desc_flags->data_ro_flags & SPDK_BLOB_READ_ONLY)) { + blob->data_ro = true; + blob->md_ro = true; + } + blob->invalid_flags = desc_flags->invalid_flags; blob->data_ro_flags = desc_flags->data_ro_flags; blob->md_ro_flags = desc_flags->md_ro_flags; @@ -2984,9 +2989,21 @@ void spdk_bs_open_blob(struct spdk_blob_store *bs, spdk_blob_id blobid, _spdk_blob_load(seq, blob, _spdk_bs_open_blob_cpl, blob); } - /* END spdk_bs_open_blob */ +/* START spdk_blob_set_read_only */ +void spdk_blob_set_read_only(struct spdk_blob *b) +{ + struct spdk_blob_data *blob = __blob_to_data(b); + + blob->data_ro = true; + blob->md_ro = true; + blob->data_ro_flags |= SPDK_BLOB_READ_ONLY; + + blob->state = SPDK_BLOB_STATE_DIRTY; +} +/* END spdk_blob_set_read_only */ + /* START spdk_blob_sync_md */ static void diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index 2a47ae27c..e36a4d331 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -240,7 +240,9 @@ struct spdk_blob_md_descriptor_extent { * mask of all flag values understood by this application. */ #define SPDK_BLOB_INVALID_FLAGS_MASK 0 -#define SPDK_BLOB_DATA_RO_FLAGS_MASK 0 + +#define SPDK_BLOB_READ_ONLY (1ULL << 0) +#define SPDK_BLOB_DATA_RO_FLAGS_MASK SPDK_BLOB_READ_ONLY #define SPDK_BLOB_MD_RO_FLAGS_MASK 0 struct spdk_blob_md_descriptor_flags { diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 6d3965d0c..08212ab78 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -341,6 +341,7 @@ blob_create(void) spdk_bs_unload(g_bs, bs_op_complete, NULL); CU_ASSERT(g_bserrno == 0); g_bs = NULL; + } static void blob_delete(void) @@ -443,6 +444,62 @@ blob_resize(void) g_bs = NULL; } +static void +blob_read_only(void) +{ + struct spdk_blob_store *bs; + struct spdk_bs_dev *dev; + struct spdk_blob *blob; + struct spdk_blob_data *blob_data; + struct spdk_bs_opts opts; + spdk_blob_id blobid; + + dev = init_dev(); + spdk_bs_opts_init(&opts); + strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); + + spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + bs = g_bs; + + spdk_bs_create_blob(bs, 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; + + spdk_blob_set_read_only(blob); + + blob_data = __blob_to_data(blob); + CU_ASSERT(blob_data->data_ro == true); + CU_ASSERT(blob_data->data_ro_flags & SPDK_BLOB_READ_ONLY); + + spdk_blob_close(blob, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + 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->data_ro == true); + CU_ASSERT(blob_data->data_ro_flags & SPDK_BLOB_READ_ONLY); + + 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 channel_ops(void) { @@ -2416,6 +2473,7 @@ int main(int argc, char **argv) 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, "blob_read_only", blob_read_only) == NULL || CU_add_test(suite, "channel_ops", channel_ops) == NULL || CU_add_test(suite, "blob_super", blob_super) == NULL || CU_add_test(suite, "blob_write", blob_write) == NULL ||