diff --git a/include/spdk_internal/virtio.h b/include/spdk_internal/virtio.h index 94eaf0a1c..777440292 100644 --- a/include/spdk_internal/virtio.h +++ b/include/spdk_internal/virtio.h @@ -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. diff --git a/lib/bdev/virtio/bdev_virtio_blk.c b/lib/bdev/virtio/bdev_virtio_blk.c index 76a774cbc..261563994 100644 --- a/lib/bdev/virtio/bdev_virtio_blk.c +++ b/lib/bdev/virtio/bdev_virtio_blk.c @@ -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; } diff --git a/lib/bdev/virtio/bdev_virtio_scsi.c b/lib/bdev/virtio/bdev_virtio_scsi.c index f10577ca5..957c12187 100644 --- a/lib/bdev/virtio/bdev_virtio_scsi.c +++ b/lib/bdev/virtio/bdev_virtio_scsi.c @@ -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) { diff --git a/lib/virtio/virtio.c b/lib/virtio/virtio.c index 4276f87bd..8e3bfbd7b 100644 --- a/lib/virtio/virtio.c +++ b/lib/virtio/virtio.c @@ -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 diff --git a/lib/virtio/virtio_pci.c b/lib/virtio/virtio_pci.c index 1246bfec4..090a7b2ee 100644 --- a/lib/virtio/virtio_pci.c +++ b/lib/virtio/virtio_pci.c @@ -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 diff --git a/lib/virtio/virtio_user.c b/lib/virtio/virtio_user.c index 8795e0a94..c688d61d6 100644 --- a/lib/virtio/virtio_user.c +++ b/lib/virtio/virtio_user.c @@ -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