Commit 166f6e9c authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Ben Walker
Browse files

bdev/virtio: add rescan safety checks



Don't allow starting full device rescan
if such scan is already in progress.

This patch also makes it possible to
start a full scan while only particular
targets are being rescanned.

Change-Id: I8677f640a4e5d9d8c486dfe1e9a58331e941a461
Signed-off-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/392373


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 5eea99fc
Loading
Loading
Loading
Loading
+41 −10
Original line number Diff line number Diff line
@@ -130,6 +130,9 @@ struct virtio_scsi_scan_base {
	/** Scan all targets on the device. */
	bool				full_scan;

	/** Start a full rescan after receiving next scan I/O response. */
	bool				restart;

	/** Additional targets to be (re)scanned. */
	TAILQ_HEAD(, virtio_scsi_scan_info) scan_queue;

@@ -697,6 +700,7 @@ bdev_virtio_poll(void *arg)
{
	struct bdev_virtio_io_channel *ch = arg;
	struct virtio_scsi_dev *svdev = ch->svdev;
	struct virtio_scsi_scan_base *scan_ctx = svdev->scan_ctx;
	void *io[32];
	uint32_t io_len[32];
	uint16_t i, cnt;
@@ -704,34 +708,41 @@ bdev_virtio_poll(void *arg)

	cnt = virtio_recv_pkts(ch->vq, (void **)io, io_len, SPDK_COUNTOF(io));
	for (i = 0; i < cnt; ++i) {
		if (spdk_unlikely(svdev->scan_ctx && io[i] == &svdev->scan_ctx->io_ctx)) {
		if (spdk_unlikely(scan_ctx && io[i] == &scan_ctx->io_ctx)) {
			if (svdev->removed) {
				_virtio_scsi_dev_scan_finish(svdev->scan_ctx, -EINTR);
				_virtio_scsi_dev_scan_finish(scan_ctx, -EINTR);
				return;
			}

			process_scan_resp(svdev->scan_ctx);
			if (scan_ctx->restart) {
				scan_ctx->restart = false;
				scan_ctx->full_scan = true;
				_virtio_scsi_dev_scan_tgt(scan_ctx, 0);
				continue;
			}

			process_scan_resp(scan_ctx);
			continue;
		}

		bdev_virtio_io_cpl(io[i]);
	}

	if (spdk_unlikely(svdev->scan_ctx && svdev->scan_ctx->needs_resend)) {
	if (spdk_unlikely(scan_ctx && scan_ctx->needs_resend)) {
		if (svdev->removed) {
			_virtio_scsi_dev_scan_finish(svdev->scan_ctx, -EINTR);
			_virtio_scsi_dev_scan_finish(scan_ctx, -EINTR);
			return;
		} else if (cnt == 0) {
			return;
		}

		rc = send_scan_io(svdev->scan_ctx);
		rc = send_scan_io(scan_ctx);
		if (rc != 0) {
			assert(svdev->scan_ctx->retries > 0);
			svdev->scan_ctx->retries--;
			if (svdev->scan_ctx->retries == 0) {
			assert(scan_ctx->retries > 0);
			scan_ctx->retries--;
			if (scan_ctx->retries == 0) {
				SPDK_ERRLOG("Target scan failed unrecoverably with rc = %d.\n", rc);
				_virtio_scsi_dev_scan_finish(svdev->scan_ctx, rc);
				_virtio_scsi_dev_scan_finish(scan_ctx, rc);
			}
		}
	}
@@ -1511,8 +1522,28 @@ virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb cb_fn,
		     void *cb_arg)
{
	struct virtio_scsi_scan_base *base;
	struct virtio_scsi_scan_info *tgt, *next_tgt;
	int rc;

	if (svdev->scan_ctx) {
		if (svdev->scan_ctx->full_scan) {
			return -EEXIST;
		}

		/* We're about to start a full rescan, so there's no need
		 * to scan particular targets afterwards.
		 */
		TAILQ_FOREACH_SAFE(tgt, &svdev->scan_ctx->scan_queue, tailq, next_tgt) {
			TAILQ_REMOVE(&svdev->scan_ctx->scan_queue, tgt, tailq);
			free(tgt);
		}

		svdev->scan_ctx->cb_fn = cb_fn;
		svdev->scan_ctx->cb_arg = cb_arg;
		svdev->scan_ctx->restart = true;
		return 0;
	}

	rc = _virtio_scsi_dev_scan_init(svdev);
	if (rc != 0) {
		return rc;