Commit 3e4ac61d authored by Jim Harris's avatar Jim Harris Committed by Daniel Verkamp
Browse files

bdev: only allow one reset per io_device at a time



This also requires vbdev modules to call spdk_bdev_reset
explicitly on the base bdev, rather than just resubmitting
the original reset bdev_io.

Signed-off-by: default avatarJim Harris <james.r.harris@intel.com>
Change-Id: Ie33d506f68506096306c9f0a9ff5e11141578b15
Reviewed-on: https://review.gerrithub.io/365712


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent dfa0618d
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -209,6 +209,11 @@ struct spdk_bdev {
	void *remove_ctx;

	TAILQ_ENTRY(spdk_bdev) link;

	/** denotes if a reset is currently in progress on this bdev */
	bool reset_in_progress;

	TAILQ_HEAD(, spdk_bdev_io) queued_resets;
};

typedef void (*spdk_bdev_io_get_buf_cb)(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io);
@@ -336,7 +341,12 @@ struct spdk_bdev_io {
	/** Member used for linking child I/Os together. */
	TAILQ_ENTRY(spdk_bdev_io) link;

	/** Per I/O context for use by the blockdev module */
	/**
	 * Per I/O context for use by the blockdev module.
	 *
	 * Note that vbdev modules may not use this field if modifying a bdev_io and resubmitting
	 * to the next lower bdev.
	 */
	uint8_t driver_ctx[0];

	/* No members may be added after driver_ctx! */
+41 −5
Original line number Diff line number Diff line
@@ -944,6 +944,37 @@ _spdk_bdev_reset_abort_channel(void *io_device, struct spdk_io_channel *ch,
	_spdk_bdev_abort_io(&mgmt_channel->need_buf_large, channel);
}

static void
_spdk_bdev_start_reset(void *ctx)
{
	struct spdk_bdev_io *bdev_io = ctx;

	spdk_for_each_channel(bdev_io->bdev, _spdk_bdev_reset_abort_channel,
			      bdev_io, _spdk_bdev_reset_dev);
}

static void
_spdk_bdev_start_next_reset(struct spdk_bdev *bdev)
{
	struct spdk_bdev_io *bdev_io;
	struct spdk_thread *thread;

	pthread_mutex_lock(&bdev->mutex);

	if (bdev->reset_in_progress || TAILQ_EMPTY(&bdev->queued_resets)) {
		pthread_mutex_unlock(&bdev->mutex);
		return;
	} else {
		bdev_io = TAILQ_FIRST(&bdev->queued_resets);
		TAILQ_REMOVE(&bdev->queued_resets, bdev_io, link);
		bdev->reset_in_progress = true;
		thread = spdk_io_channel_get_thread(bdev_io->ch->channel);
		spdk_thread_send_msg(thread, _spdk_bdev_start_reset, bdev_io);
	}

	pthread_mutex_unlock(&bdev->mutex);
}

int
spdk_bdev_reset(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
		spdk_bdev_io_completion_cb cb, void *cb_arg)
@@ -963,11 +994,11 @@ spdk_bdev_reset(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
	bdev_io->type = SPDK_BDEV_IO_TYPE_RESET;
	spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);

	/* First, abort all I/O queued up waiting for buffers. */
	spdk_for_each_channel(bdev,
			      _spdk_bdev_reset_abort_channel,
			      bdev_io,
			      _spdk_bdev_reset_dev);
	pthread_mutex_lock(&bdev->mutex);
	TAILQ_INSERT_TAIL(&bdev->queued_resets, bdev_io, link);
	pthread_mutex_unlock(&bdev->mutex);

	_spdk_bdev_start_next_reset(bdev);

	return 0;
}
@@ -1093,6 +1124,8 @@ spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status sta
			/* Increase the blockdev generation */
			bdev_io->bdev->gencnt++;
		}
		bdev_io->bdev->reset_in_progress = false;
		_spdk_bdev_start_next_reset(bdev_io->bdev);
	} else {
		/*
		 * Check the gencnt, to see if this I/O was issued before the most
@@ -1242,6 +1275,9 @@ spdk_bdev_register(struct spdk_bdev *bdev)
	/* initialize the reset generation value to zero */
	bdev->gencnt = 0;

	bdev->reset_in_progress = false;
	TAILQ_INIT(&bdev->queued_resets);

	spdk_io_device_register(bdev, spdk_bdev_channel_create, spdk_bdev_channel_destroy,
				sizeof(struct spdk_bdev_channel));

+24 −12
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "spdk/conf.h"
#include "spdk/endian.h"
#include "spdk/string.h"
#include "spdk/io_channel.h"

#include "spdk_internal/bdev.h"
#include "spdk_internal/log.h"
@@ -96,22 +97,21 @@ split_flush(struct split_disk *split_disk, struct spdk_bdev_io *bdev_io)
}

static void
split_reset(struct split_disk *split_disk, struct spdk_bdev_io *bdev_io)
_vbdev_split_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
	/*
	 * No offset to modify for reset - pass the I/O through unmodified.
	 *
	 * However, we do need to increment the generation count for the split bdev,
	 * since the spdk_bdev_io_complete() path that normally updates it will not execute
	 * after we resubmit the I/O to the base_bdev.
	 */
	split_disk->disk.gencnt++;
	struct spdk_bdev_io *split_io = cb_arg;
	struct spdk_io_channel *base_ch = *(struct spdk_io_channel **)split_io->driver_ctx;

	spdk_put_io_channel(base_ch);
	spdk_bdev_io_complete(split_io, success);
	spdk_bdev_free_io(bdev_io);
}

static void
vbdev_split_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
{
	struct split_disk *split_disk = bdev_io->bdev->ctxt;
	struct spdk_io_channel *base_ch;

	/* Modify the I/O to adjust for the offset within the base bdev. */
	switch (bdev_io->type) {
@@ -128,8 +128,10 @@ vbdev_split_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev
		split_flush(split_disk, bdev_io);
		break;
	case SPDK_BDEV_IO_TYPE_RESET:
		split_reset(split_disk, bdev_io);
		break;
		base_ch = spdk_get_io_channel(split_disk->base_bdev);
		*(struct spdk_io_channel **)bdev_io->driver_ctx = base_ch;
		spdk_bdev_reset(split_disk->base_bdev, base_ch, _vbdev_split_complete_reset, bdev_io);
		return;
	default:
		SPDK_ERRLOG("split: unknown I/O type %d\n", bdev_io->type);
		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
@@ -416,5 +418,15 @@ vbdev_split_fini(void)
	}
}

SPDK_VBDEV_MODULE_REGISTER(vbdev_split_init, vbdev_split_fini, NULL, NULL, NULL)
static int
vbdev_split_get_ctx_size(void)
{
	/*
	 * Note: this context is only used for RESET operations, since it is the only
	 *  I/O type that does not just resubmit to the base bdev.
	 */
	return sizeof(struct spdk_io_channel *);
}

SPDK_VBDEV_MODULE_REGISTER(vbdev_split_init, vbdev_split_fini, NULL, vbdev_split_get_ctx_size, NULL)
SPDK_LOG_REGISTER_TRACE_FLAG("vbdev_split", SPDK_TRACE_VBDEV_SPLIT)