Commit 62844ae3 authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

virtio: allow config read/write to fail



For vhost-user it's a protocol feature that can simply
be not supported. The subsequent patch introduces an extra
check that may cause config read/write to fail.

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


Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent 48322f0c
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -98,9 +98,9 @@ struct virtio_dev {
};

struct virtio_dev_ops {
	void (*read_dev_cfg)(struct virtio_dev *hw, size_t offset,
	int (*read_dev_cfg)(struct virtio_dev *hw, size_t offset,
			    void *dst, int len);
	void (*write_dev_cfg)(struct virtio_dev *hw, size_t offset,
	int (*write_dev_cfg)(struct virtio_dev *hw, size_t offset,
			     const void *src, int len);
	uint8_t (*get_status)(struct virtio_dev *hw);
	void (*set_status)(struct virtio_dev *hw, uint8_t status);
@@ -392,8 +392,9 @@ void virtio_dev_set_status(struct virtio_dev *vdev, uint8_t flag);
 * \param offset offset in bytes
 * \param src pointer to data to copy from
 * \param len length of data to copy in bytes
 * \return 0 on success, negative errno otherwise
 */
void virtio_dev_write_dev_config(struct virtio_dev *vdev, size_t offset, const void *src, int len);
int virtio_dev_write_dev_config(struct virtio_dev *vdev, size_t offset, const void *src, int len);

/**
 * Read raw data from the device config at given offset.  This call does not
@@ -403,8 +404,9 @@ void virtio_dev_write_dev_config(struct virtio_dev *vdev, size_t offset, const v
 * \param offset offset in bytes
 * \param dst pointer to buffer to copy data into
 * \param len length of data to copy in bytes
 * \return 0 on success, negative errno otherwise
 */
void virtio_dev_read_dev_config(struct virtio_dev *vdev, size_t offset, void *dst, int len);
int virtio_dev_read_dev_config(struct virtio_dev *vdev, size_t offset, void *dst, int len);

/**
 * Get backend-specific ops for given device.
+27 −8
Original line number Diff line number Diff line
@@ -352,8 +352,13 @@ virtio_blk_dev_init(struct virtio_blk_dev *bvdev, uint16_t max_queues)
	int rc;

	if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE)) {
		virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, blk_size),
		rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, blk_size),
						&block_size, sizeof(block_size));
		if (rc) {
			SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
			return rc;
		}

		if (block_size == 0 || block_size % 512 != 0) {
			SPDK_ERRLOG("%s: invalid block size (%"PRIu32"). Must be "
				    "a multiple of 512.\n", vdev->name, block_size);
@@ -363,8 +368,12 @@ virtio_blk_dev_init(struct virtio_blk_dev *bvdev, uint16_t max_queues)
		block_size = 512;
	}

	virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, capacity),
	rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, capacity),
					&capacity, sizeof(capacity));
	if (rc) {
		SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
		return rc;
	}

	/* `capacity` is a number of 512-byte sectors. */
	num_blocks = capacity * 512 / block_size;
@@ -381,8 +390,12 @@ virtio_blk_dev_init(struct virtio_blk_dev *bvdev, uint16_t max_queues)
	}

	if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_MQ)) {
		virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues),
		rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues),
						&host_max_queues, sizeof(host_max_queues));
		if (rc) {
			SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
			return rc;
		}
	} else {
		host_max_queues = 1;
	}
@@ -478,8 +491,14 @@ virtio_pci_blk_dev_create(const char *name, struct virtio_pci_ctx *pci_ctx)

	/* TODO: add a way to limit usable virtqueues */
	if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_MQ)) {
		virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues),
		rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues),
						&num_queues, sizeof(num_queues));
		if (rc) {
			SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
			virtio_dev_destruct(vdev);
			free(bvdev);
			return NULL;
		}
	} else {
		num_queues = 1;
	}
+8 −2
Original line number Diff line number Diff line
@@ -337,8 +337,14 @@ virtio_pci_scsi_dev_create(const char *name, struct virtio_pci_ctx *pci_ctx)
		return NULL;
	}

	virtio_dev_read_dev_config(vdev, offsetof(struct virtio_scsi_config, num_queues),
	rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_scsi_config, num_queues),
					&num_queues, sizeof(num_queues));
	if (rc) {
		SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
		virtio_dev_destruct(vdev);
		free(svdev);
		return NULL;
	}

	rc = virtio_scsi_dev_init(svdev, num_queues);
	if (rc != 0) {
+4 −4
Original line number Diff line number Diff line
@@ -683,18 +683,18 @@ virtio_dev_release_queue(struct virtio_dev *vdev, uint16_t index)
	pthread_mutex_unlock(&vdev->mutex);
}

void
int
virtio_dev_read_dev_config(struct virtio_dev *dev, size_t offset,
			   void *dst, int length)
{
	virtio_dev_backend_ops(dev)->read_dev_cfg(dev, offset, dst, length);
	return virtio_dev_backend_ops(dev)->read_dev_cfg(dev, offset, dst, length);
}

void
int
virtio_dev_write_dev_config(struct virtio_dev *dev, size_t offset,
			    const void *src, int length)
{
	virtio_dev_backend_ops(dev)->write_dev_cfg(dev, offset, src, length);
	return virtio_dev_backend_ops(dev)->write_dev_cfg(dev, offset, src, length);
}

void
+6 −2
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi)
	spdk_mmio_write_4(hi, val >> 32);
}

static void
static int
modern_read_dev_config(struct virtio_dev *dev, size_t offset,
		       void *dst, int length)
{
@@ -165,9 +165,11 @@ modern_read_dev_config(struct virtio_dev *dev, size_t offset,

		new_gen = spdk_mmio_read_1(&hw->common_cfg->config_generation);
	} while (old_gen != new_gen);

	return 0;
}

static void
static int
modern_write_dev_config(struct virtio_dev *dev, size_t offset,
			const void *src, int length)
{
@@ -178,6 +180,8 @@ modern_write_dev_config(struct virtio_dev *dev, size_t offset,
	for (i = 0;  i < length; i++) {
		spdk_mmio_write_1(((uint8_t *)hw->dev_cfg) + offset + i, *p++);
	}

	return 0;
}

static uint64_t
Loading