Commit 3959e397 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Jim Harris
Browse files

nvme: Add new detach to a detach context while it is being polled



This update will allow us to use spdk_nvme_detach_async() and
spdk_nvme_detach_poll_async() easier to aggregate multiple detachments.

Previously, we could do:
    spdk_nvme_detach_async()
    spdk_nvme_detach_async()
    spdk_nvme_detach_async()
and then started doing spdk_nvme_detach_poll_async().

Hence aggregating multiple detachments is already supported.

After this patch, the following sequence is possible:
    spdk_nvme_detach_async() = 0
    spdk_nvme_detach_async() = 0
    spdk_nvme_detach_async() = 0
    spdk_nvme_detach_poll_async() = -EAGAIN
    spdk_nvme_detach_async() = 0
    spdk_nvme_detach_async() = 0
    spdk_nvme_detach_poll_async() = -EAGAIN
    spdk_nvme_detach_poll_async() = -EAGAIN
    spdk_nvme_detach_poll_async() = -EAGAIN
    spdk_nvme_detach_poll_async() = 0

The actual changes is to remove the variable polling_started from
struct spdk_nvme_detach_ctx because it is not necessary anymore.

Clarify this change via updating the header file and CHANGELOG.
Verify this change by unit test.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Iebdf6c27c5304a2097b7084c315ccc99634ffa1e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8468


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
parent 4fe4040a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -63,6 +63,9 @@ the spdk_nvme_ctrlr_opts structure prior to controller attach.
Add a new function `spdk_nvme_detach_poll` to simplify a common use case to continue
polling until all detachments complete.

An existing function `spdk_nvme_detach_async` was updated to add one or more detachments
to an active context while it is being polled.

### rpc

New RPC `bdev_rbd_register_cluster` and `bdev_rbd_unregister_cluster` was added, it allows to create
+0 −5
Original line number Diff line number Diff line
@@ -180,9 +180,6 @@ spdk_nvme_detach_async(struct spdk_nvme_ctrlr *ctrlr,
			return -ENOMEM;
		}
		TAILQ_INIT(&detach_ctx->head);
	} else if (detach_ctx->polling_started) {
		SPDK_ERRLOG("Busy at polling detachment now.\n");
		return -EBUSY;
	}

	rc = nvme_ctrlr_detach_async(ctrlr, &ctx);
@@ -214,8 +211,6 @@ spdk_nvme_detach_poll_async(struct spdk_nvme_detach_ctx *detach_ctx)
		return -EINVAL;
	}

	detach_ctx->polling_started = true;

	TAILQ_FOREACH_SAFE(ctx, &detach_ctx->head, link, tmp_ctx) {
		TAILQ_REMOVE(&detach_ctx->head, ctx, link);

+0 −1
Original line number Diff line number Diff line
@@ -914,7 +914,6 @@ struct nvme_ctrlr_detach_ctx {

struct spdk_nvme_detach_ctx {
	TAILQ_HEAD(, nvme_ctrlr_detach_ctx)	head;
	bool					polling_started;
};

struct nvme_driver {
+50 −0
Original line number Diff line number Diff line
@@ -79,12 +79,18 @@ nvme_ctrlr_destruct_async(struct spdk_nvme_ctrlr *ctrlr, struct nvme_ctrlr_detac
{
	ut_destruct_called = true;
	ctrlr->is_destructed = true;

	ctx->shutdown_complete = true;
}

int
nvme_ctrlr_destruct_poll_async(struct spdk_nvme_ctrlr *ctrlr,
			       struct nvme_ctrlr_detach_ctx *ctx)
{
	if (!ctx->shutdown_complete) {
		return -EAGAIN;
	}

	if (ctx->cb_fn) {
		ctx->cb_fn(ctrlr);
	}
@@ -1496,6 +1502,7 @@ test_spdk_nvme_detach_async(void)
	struct spdk_nvme_ctrlr ctrlr1, ctrlr2;
	struct nvme_driver test_driver;
	struct spdk_nvme_detach_ctx *detach_ctx;
	struct nvme_ctrlr_detach_ctx *ctx;

	detach_ctx = NULL;
	memset(&ctrlr1, 0, sizeof(ctrlr1));
@@ -1556,6 +1563,49 @@ test_spdk_nvme_detach_async(void)
	CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs) == true);
	CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == true);

	/* Test if ctrlr2 can be detached by using the same context that
	 * ctrlr1 uses while ctrlr1 is being detached.
	 */
	detach_ctx = NULL;
	memset(&ctrlr1, 0, sizeof(ctrlr1));
	ctrlr1.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
	memset(&ctrlr2, 0, sizeof(ctrlr2));
	ctrlr2.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
	TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr1, tailq);
	TAILQ_INSERT_TAIL(&test_driver.shared_attached_ctrlrs, &ctrlr2, tailq);

	rc = spdk_nvme_detach_async(&ctrlr1, &detach_ctx);
	CU_ASSERT(rc == 0);
	CU_ASSERT(ctrlr1.is_destructed == true);
	SPDK_CU_ASSERT_FATAL(detach_ctx != NULL);

	ctx = TAILQ_FIRST(&detach_ctx->head);
	SPDK_CU_ASSERT_FATAL(ctx != NULL);
	CU_ASSERT(ctx->ctrlr == &ctrlr1);
	CU_ASSERT(ctx->shutdown_complete == true);

	/* Set ctx->shutdown_complete for ctrlr1 to false to allow ctrlr2 to
	 * add to detach_ctx while spdk_nvme_detach_poll_async() is being
	 * executed.
	 */
	ctx->shutdown_complete = false;

	rc = spdk_nvme_detach_poll_async(detach_ctx);
	CU_ASSERT(rc == -EAGAIN);

	rc = spdk_nvme_detach_async(&ctrlr2, &detach_ctx);
	CU_ASSERT(rc == 0);
	CU_ASSERT(ctrlr2.is_destructed == true);

	/* After ctrlr2 is added to detach_ctx, set ctx->shutdown_complete for
	 * ctrlr1 to true to complete spdk_nvme_detach_poll_async().
	 */
	ctx->shutdown_complete = true;

	rc = spdk_nvme_detach_poll_async(detach_ctx);
	CU_ASSERT(rc == 0);
	CU_ASSERT(TAILQ_EMPTY(&test_driver.shared_attached_ctrlrs) == true);

	g_spdk_nvme_driver = NULL;
	pthread_mutex_destroy(&test_driver.lock);
	MOCK_CLEAR(nvme_ctrlr_get_ref_count);