Commit 9d5dd7cc authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Jim Harris
Browse files

bdev: keep a list of quiesced ranges in bdev_module



On quiesce add the range to the list in the range locked callback. On
unquiesce check and remove the range from the list before calling
unlock.

Change-Id: If2f4dd5dbe645b82981b8b9b0ce80ffab3353186
Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/18004


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 9e386832
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -147,7 +147,8 @@ struct spdk_bdev_module {
	 */
	struct __bdev_module_internal_fields {
		/**
		 * Protects action_in_progress. Take no locks while holding this one.
		 * Protects action_in_progress and quiesced_ranges.
		 * Take no locks while holding this one.
		 */
		struct spdk_spinlock spinlock;

@@ -159,6 +160,11 @@ struct spdk_bdev_module {
		 */
		uint32_t action_in_progress;

		/**
		 * List of quiesced lba ranges in all bdevs of this module.
		 */
		TAILQ_HEAD(, lba_range) quiesced_ranges;

		TAILQ_ENTRY(spdk_bdev_module) tailq;
	} internal;
};
+45 −3
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ struct lba_range {
	struct spdk_thread		*owner_thread;
	struct spdk_bdev_channel	*owner_ch;
	TAILQ_ENTRY(lba_range)		tailq;
	TAILQ_ENTRY(lba_range)		tailq_module;
};

static struct spdk_bdev_opts	g_bdev_opts = {
@@ -8592,6 +8593,7 @@ spdk_bdev_module_list_add(struct spdk_bdev_module *bdev_module)
	}

	spdk_spin_init(&bdev_module->internal.spinlock);
	TAILQ_INIT(&bdev_module->internal.quiesced_ranges);

	/*
	 * Modules with examine callbacks must be initialized first, so they are
@@ -9511,7 +9513,7 @@ struct bdev_quiesce_ctx {
};

static void
bdev_quiesce_lock_range_cb(struct lba_range *range, void *ctx, int status)
bdev_unquiesce_range_unlocked(struct lba_range *range, void *ctx, int status)
{
	struct bdev_quiesce_ctx *quiesce_ctx = ctx;

@@ -9522,6 +9524,26 @@ bdev_quiesce_lock_range_cb(struct lba_range *range, void *ctx, int status)
	free(quiesce_ctx);
}

static void
bdev_quiesce_range_locked(struct lba_range *range, void *ctx, int status)
{
	struct bdev_quiesce_ctx *quiesce_ctx = ctx;
	struct spdk_bdev_module *module = range->bdev->module;

	if (status != 0) {
		goto out;
	}

	spdk_spin_lock(&module->internal.spinlock);
	TAILQ_INSERT_TAIL(&module->internal.quiesced_ranges, range, tailq_module);
	spdk_spin_unlock(&module->internal.spinlock);
out:
	if (quiesce_ctx->cb_fn != NULL) {
		quiesce_ctx->cb_fn(quiesce_ctx->cb_arg, status);
	}
	free(quiesce_ctx);
}

static int
_spdk_bdev_quiesce(struct spdk_bdev *bdev, struct spdk_bdev_module *module,
		   uint64_t offset, uint64_t length,
@@ -9549,9 +9571,29 @@ _spdk_bdev_quiesce(struct spdk_bdev *bdev, struct spdk_bdev_module *module,
	quiesce_ctx->cb_arg = cb_arg;

	if (unquiesce) {
		rc = _bdev_unlock_lba_range(bdev, offset, length, bdev_quiesce_lock_range_cb, quiesce_ctx);
		struct lba_range *range;

		/* Make sure the specified range is actually quiesced in the specified module and
		 * then remove it from the list. Note that the range must match exactly.
		 */
		spdk_spin_lock(&module->internal.spinlock);
		TAILQ_FOREACH(range, &module->internal.quiesced_ranges, tailq_module) {
			if (range->bdev == bdev && range->offset == offset && range->length == length) {
				TAILQ_REMOVE(&module->internal.quiesced_ranges, range, tailq_module);
				break;
			}
		}
		spdk_spin_unlock(&module->internal.spinlock);

		if (range == NULL) {
			SPDK_ERRLOG("The range to unquiesce was not found.\n");
			free(quiesce_ctx);
			return -EINVAL;
		}

		rc = _bdev_unlock_lba_range(bdev, offset, length, bdev_unquiesce_range_unlocked, quiesce_ctx);
	} else {
		rc = _bdev_lock_lba_range(bdev, NULL, offset, length, bdev_quiesce_lock_range_cb, quiesce_ctx);
		rc = _bdev_lock_lba_range(bdev, NULL, offset, length, bdev_quiesce_range_locked, quiesce_ctx);
	}

	if (rc != 0) {
+16 −0
Original line number Diff line number Diff line
@@ -5081,6 +5081,11 @@ bdev_quiesce(void)
	CU_ASSERT(range->offset == 0);
	CU_ASSERT(range->length == bdev->blockcnt);
	CU_ASSERT(range->owner_ch == NULL);
	range = TAILQ_FIRST(&bdev_ut_if.internal.quiesced_ranges);
	SPDK_CU_ASSERT_FATAL(range != NULL);
	CU_ASSERT(range->offset == 0);
	CU_ASSERT(range->length == bdev->blockcnt);
	CU_ASSERT(range->owner_ch == NULL);

	g_unlock_lba_range_done = false;
	rc = spdk_bdev_unquiesce(bdev, &bdev_ut_if, bdev_unquiesce_done, &ctx1);
@@ -5090,6 +5095,7 @@ bdev_quiesce(void)

	CU_ASSERT(g_unlock_lba_range_done == true);
	CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges));
	CU_ASSERT(TAILQ_EMPTY(&bdev_ut_if.internal.quiesced_ranges));

	g_lock_lba_range_done = false;
	rc = spdk_bdev_quiesce_range(bdev, &bdev_ut_if, 20, 10, bdev_quiesce_done, &ctx1);
@@ -5102,9 +5108,18 @@ bdev_quiesce(void)
	CU_ASSERT(range->offset == 20);
	CU_ASSERT(range->length == 10);
	CU_ASSERT(range->owner_ch == NULL);
	range = TAILQ_FIRST(&bdev_ut_if.internal.quiesced_ranges);
	SPDK_CU_ASSERT_FATAL(range != NULL);
	CU_ASSERT(range->offset == 20);
	CU_ASSERT(range->length == 10);
	CU_ASSERT(range->owner_ch == NULL);

	/* Unlocks must exactly match a lock. */
	g_unlock_lba_range_done = false;
	rc = spdk_bdev_unquiesce_range(bdev, &bdev_ut_if, 20, 1, bdev_unquiesce_done, &ctx1);
	CU_ASSERT(rc == -EINVAL);
	CU_ASSERT(g_unlock_lba_range_done == false);

	rc = spdk_bdev_unquiesce_range(bdev, &bdev_ut_if, 20, 10, bdev_unquiesce_done, &ctx1);
	CU_ASSERT(rc == 0);
	spdk_delay_us(100);
@@ -5112,6 +5127,7 @@ bdev_quiesce(void)

	CU_ASSERT(g_unlock_lba_range_done == true);
	CU_ASSERT(TAILQ_EMPTY(&channel->locked_ranges));
	CU_ASSERT(TAILQ_EMPTY(&bdev_ut_if.internal.quiesced_ranges));

	spdk_put_io_channel(io_ch);
	spdk_bdev_close(desc);