diff --git a/include/spdk_internal/lvolstore.h b/include/spdk_internal/lvolstore.h index 0d1df225c..89557a681 100644 --- a/include/spdk_internal/lvolstore.h +++ b/include/spdk_internal/lvolstore.h @@ -89,6 +89,7 @@ struct spdk_lvol_store { int lvols_opened; bool destruct; TAILQ_HEAD(, spdk_lvol) lvols; + TAILQ_HEAD(, spdk_lvol) pending_lvols; bool on_list; TAILQ_ENTRY(spdk_lvol_store) link; char name[SPDK_LVS_NAME_MAX]; diff --git a/lib/lvol/lvol.c b/lib/lvol/lvol.c index 6142afcf4..00487ce05 100644 --- a/lib/lvol/lvol.c +++ b/lib/lvol/lvol.c @@ -374,6 +374,7 @@ _spdk_lvs_load_cb(void *cb_arg, struct spdk_blob_store *bs, int lvolerrno) lvs->blobstore = bs; lvs->bs_dev = req->bs_dev; TAILQ_INIT(&lvs->lvols); + TAILQ_INIT(&lvs->pending_lvols); req->lvol_store = lvs; @@ -535,6 +536,7 @@ _spdk_lvs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int lvserrno) assert(bs != NULL); lvs->blobstore = bs; TAILQ_INIT(&lvs->lvols); + TAILQ_INIT(&lvs->pending_lvols); SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol store initialized\n"); @@ -961,6 +963,8 @@ _spdk_lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno) spdk_blob_id blob_id = spdk_blob_get_id(blob); struct spdk_lvol *lvol = req->lvol; + TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link); + if (lvolerrno < 0) { free(lvol); req->cb_fn(req->cb_arg, NULL, lvolerrno); @@ -994,6 +998,7 @@ _spdk_lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno) struct spdk_blob_store *bs; if (lvolerrno < 0) { + TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link); free(req->lvol); assert(req->cb_fn != NULL); req->cb_fn(req->cb_arg, NULL, lvolerrno); @@ -1048,6 +1053,13 @@ _spdk_lvs_verify_lvol_name(struct spdk_lvol_store *lvs, const char *name) } } + TAILQ_FOREACH(tmp, &lvs->pending_lvols, link) { + if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) { + SPDK_ERRLOG("lvol with name %s is being already created\n", name); + return -EEXIST; + } + } + return 0; } @@ -1090,6 +1102,7 @@ spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz, lvol->close_only = false; lvol->thin_provision = thin_provision; snprintf(lvol->name, sizeof(lvol->name), "%s", name); + TAILQ_INSERT_TAIL(&lvol->lvol_store->pending_lvols, lvol, link); spdk_uuid_generate(&lvol->uuid); spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid); req->lvol = lvol; @@ -1150,6 +1163,7 @@ spdk_lvol_create_snapshot(struct spdk_lvol *origlvol, const char *snapshot_name, newlvol->lvol_store = origlvol->lvol_store; snprintf(newlvol->name, sizeof(newlvol->name), "%s", snapshot_name); + TAILQ_INSERT_TAIL(&newlvol->lvol_store->pending_lvols, newlvol, link); spdk_uuid_generate(&newlvol->uuid); spdk_uuid_fmt_lower(newlvol->uuid_str, sizeof(newlvol->uuid_str), &newlvol->uuid); snapshot_xattrs.count = SPDK_COUNTOF(xattr_names); @@ -1207,6 +1221,7 @@ spdk_lvol_create_clone(struct spdk_lvol *origlvol, const char *clone_name, newlvol->lvol_store = lvs; snprintf(newlvol->name, sizeof(newlvol->name), "%s", clone_name); + TAILQ_INSERT_TAIL(&newlvol->lvol_store->pending_lvols, newlvol, link); spdk_uuid_generate(&newlvol->uuid); spdk_uuid_fmt_lower(newlvol->uuid_str, sizeof(newlvol->uuid_str), &newlvol->uuid); clone_xattrs.count = SPDK_COUNTOF(xattr_names); diff --git a/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c b/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c index 44382179e..abef72c63 100644 --- a/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c +++ b/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c @@ -176,6 +176,7 @@ spdk_lvs_load(struct spdk_bs_dev *dev, lvs = calloc(1, sizeof(*lvs)); SPDK_CU_ASSERT_FATAL(lvs != NULL); TAILQ_INIT(&lvs->lvols); + TAILQ_INIT(&lvs->pending_lvols); g_lvol_store = lvs; for (i = 0; i < g_num_lvols; i++) { _lvol_create(lvs); @@ -269,6 +270,7 @@ spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o, lvs = calloc(1, sizeof(*lvs)); SPDK_CU_ASSERT_FATAL(lvs != NULL); TAILQ_INIT(&lvs->lvols); + TAILQ_INIT(&lvs->pending_lvols); spdk_uuid_generate(&lvs->uuid); snprintf(lvs->name, sizeof(lvs->name), "%s", o->name); lvs->bs_dev = bs_dev; diff --git a/test/unit/lib/lvol/lvol.c/lvol_ut.c b/test/unit/lib/lvol/lvol.c/lvol_ut.c index b52eb7133..e56b62418 100644 --- a/test/unit/lib/lvol/lvol.c/lvol_ut.c +++ b/test/unit/lib/lvol/lvol.c/lvol_ut.c @@ -1627,6 +1627,27 @@ lvol_names(void) spdk_lvol_close(lvol2, close_cb, NULL); spdk_lvol_destroy(lvol2, destroy_cb, NULL); + /* Simulate creating two lvols with same name simultaneously. */ + lvol = calloc(1, sizeof(*lvol)); + SPDK_CU_ASSERT_FATAL(lvol != NULL); + snprintf(lvol->name, sizeof(lvol->name), "tmp_name"); + TAILQ_INSERT_TAIL(&lvs->pending_lvols, lvol, link); + rc = spdk_lvol_create(lvs, "tmp_name", 1, false, lvol_op_with_handle_complete, NULL); + CU_ASSERT(rc == -EEXIST); + + /* Remove name from temporary list and try again. */ + TAILQ_REMOVE(&lvs->pending_lvols, lvol, link); + free(lvol); + + rc = spdk_lvol_create(lvs, "tmp_name", 1, false, lvol_op_with_handle_complete, NULL); + CU_ASSERT(rc == 0); + CU_ASSERT(g_lvserrno == 0); + SPDK_CU_ASSERT_FATAL(g_lvol != NULL); + lvol = g_lvol; + + spdk_lvol_close(lvol, close_cb, NULL); + spdk_lvol_destroy(lvol, destroy_cb, NULL); + g_lvserrno = -1; rc = spdk_lvs_destroy(lvs, lvol_store_op_complete, NULL); CU_ASSERT(rc == 0);