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: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/417458 Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
48322f0c37
commit
62844ae3ca
@ -98,10 +98,10 @@ struct virtio_dev {
|
||||
};
|
||||
|
||||
struct virtio_dev_ops {
|
||||
void (*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,
|
||||
const void *src, int len);
|
||||
int (*read_dev_cfg)(struct virtio_dev *hw, size_t offset,
|
||||
void *dst, int len);
|
||||
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.
|
||||
|
@ -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),
|
||||
&block_size, sizeof(block_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),
|
||||
&capacity, sizeof(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),
|
||||
&host_max_queues, sizeof(host_max_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),
|
||||
&num_queues, sizeof(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;
|
||||
}
|
||||
|
@ -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),
|
||||
&num_queues, sizeof(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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -215,7 +215,7 @@ virtio_user_dev_setup(struct virtio_dev *vdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
virtio_user_read_dev_config(struct virtio_dev *vdev, size_t offset,
|
||||
void *dst, int length)
|
||||
{
|
||||
@ -227,13 +227,14 @@ virtio_user_read_dev_config(struct virtio_dev *vdev, size_t offset,
|
||||
|
||||
if (dev->ops->send_request(dev, VHOST_USER_GET_CONFIG, &cfg) < 0) {
|
||||
SPDK_ERRLOG("get_config failed: %s\n", spdk_strerror(errno));
|
||||
return;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
memcpy(dst, cfg.region + offset, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
virtio_user_write_dev_config(struct virtio_dev *vdev, size_t offset,
|
||||
const void *src, int length)
|
||||
{
|
||||
@ -246,8 +247,10 @@ virtio_user_write_dev_config(struct virtio_dev *vdev, size_t offset,
|
||||
|
||||
if (dev->ops->send_request(dev, VHOST_USER_SET_CONFIG, &cfg) < 0) {
|
||||
SPDK_ERRLOG("set_config failed: %s\n", spdk_strerror(errno));
|
||||
return;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user