Introduce new wrappers to set/reset guest notifiers for the virtio device in the vhost device module: vhost_dev_assign_guest_notifiers ->set_guest_notifiers(..., ..., true); vhost_dev_drop_guest_notifiers ->set_guest_notifiers(..., ..., false); This is a preliminary step to refactor code, so the set_guest_notifiers methods could be called based on the vhost device state. Update all vhost used devices to use these wrappers instead of direct method call.
Signed-off-by: Dima Stepanov <dimas...@yandex-team.ru> --- backends/cryptodev-vhost.c | 26 +++++++++++++++----------- backends/vhost-user.c | 16 +++++----------- hw/block/vhost-user-blk.c | 15 +++++---------- hw/net/vhost_net.c | 30 +++++++++++++++++------------- hw/scsi/vhost-scsi-common.c | 15 +++++---------- hw/virtio/vhost-user-fs.c | 17 +++++++---------- hw/virtio/vhost-vsock.c | 18 ++++++++---------- hw/virtio/vhost.c | 38 ++++++++++++++++++++++++++++++++++++++ hw/virtio/virtio.c | 13 +++++++++++++ include/hw/virtio/vhost.h | 4 ++++ include/hw/virtio/virtio.h | 1 + 11 files changed, 118 insertions(+), 75 deletions(-) diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c index 8337c9a..4522195 100644 --- a/backends/cryptodev-vhost.c +++ b/backends/cryptodev-vhost.c @@ -169,16 +169,13 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc, int cryptodev_vhost_start(VirtIODevice *dev, int total_queues) { VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); - VirtioBusState *vbus = VIRTIO_BUS(qbus); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); int r, e; int i; CryptoDevBackend *b = vcrypto->cryptodev; CryptoDevBackendVhost *vhost_crypto; CryptoDevBackendClient *cc; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(dev)) { error_report("binding does not support guest notifiers"); return -ENOSYS; } @@ -198,9 +195,13 @@ int cryptodev_vhost_start(VirtIODevice *dev, int total_queues) } } - r = k->set_guest_notifiers(qbus->parent, total_queues, true); + /* + * Since all the states are handled by one vhost device, + * use the first one in array. + */ + vhost_crypto = cryptodev_get_vhost(b->conf.peers.ccs[0], b, 0); + r = vhost_dev_assign_guest_notifiers(&vhost_crypto->dev, dev, total_queues); if (r < 0) { - error_report("error binding guest notifier: %d", -r); goto err; } @@ -232,7 +233,8 @@ err_start: vhost_crypto = cryptodev_get_vhost(cc, b, i); cryptodev_vhost_stop_one(vhost_crypto, dev); } - e = k->set_guest_notifiers(qbus->parent, total_queues, false); + vhost_crypto = cryptodev_get_vhost(b->conf.peers.ccs[0], b, 0); + e = vhost_dev_drop_guest_notifiers(&vhost_crypto->dev, dev, total_queues); if (e < 0) { error_report("vhost guest notifier cleanup failed: %d", e); } @@ -242,9 +244,6 @@ err: void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); - VirtioBusState *vbus = VIRTIO_BUS(qbus); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev); CryptoDevBackend *b = vcrypto->cryptodev; CryptoDevBackendVhost *vhost_crypto; @@ -259,7 +258,12 @@ void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues) cryptodev_vhost_stop_one(vhost_crypto, dev); } - r = k->set_guest_notifiers(qbus->parent, total_queues, false); + /* + * Since all the states are handled by one vhost device, + * use the first one in array. + */ + vhost_crypto = cryptodev_get_vhost(b->conf.peers.ccs[0], b, 0); + r = vhost_dev_drop_guest_notifiers(&vhost_crypto->dev, dev, total_queues); if (r < 0) { error_report("vhost guest notifier cleanup failed: %d", r); } diff --git a/backends/vhost-user.c b/backends/vhost-user.c index 2bf3406..e116bc6 100644 --- a/backends/vhost-user.c +++ b/backends/vhost-user.c @@ -60,15 +60,13 @@ vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev, void vhost_user_backend_start(VhostUserBackend *b) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret, i ; if (b->started) { return; } - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(b->vdev)) { error_report("binding does not support guest notifiers"); return; } @@ -78,9 +76,8 @@ vhost_user_backend_start(VhostUserBackend *b) return; } - ret = k->set_guest_notifiers(qbus->parent, b->dev.nvqs, true); + ret = vhost_dev_assign_guest_notifiers(&b->dev, b->vdev, b->dev.nvqs); if (ret < 0) { - error_report("Error binding guest notifier"); goto err_host_notifiers; } @@ -104,7 +101,7 @@ vhost_user_backend_start(VhostUserBackend *b) return; err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, b->dev.nvqs, false); + vhost_dev_drop_guest_notifiers(&b->dev, b->vdev, b->dev.nvqs); err_host_notifiers: vhost_dev_disable_notifiers(&b->dev, b->vdev); } @@ -112,8 +109,6 @@ err_host_notifiers: void vhost_user_backend_stop(VhostUserBackend *b) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret = 0; if (!b->started) { @@ -122,9 +117,8 @@ vhost_user_backend_stop(VhostUserBackend *b) vhost_dev_stop(&b->dev, b->vdev); - if (k->set_guest_notifiers) { - ret = k->set_guest_notifiers(qbus->parent, - b->dev.nvqs, false); + if (virtio_device_guest_notifiers_initialized(b->vdev)) { + ret = vhost_dev_drop_guest_notifiers(&b->dev, b->vdev, b->dev.nvqs); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d", ret); } diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 17df533..70d7842 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -109,11 +109,9 @@ const VhostDevConfigOps blk_ops = { static int vhost_user_blk_start(VirtIODevice *vdev) { VHostUserBlk *s = VHOST_USER_BLK(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int i, ret; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { error_report("binding does not support guest notifiers"); return -ENOSYS; } @@ -124,9 +122,8 @@ static int vhost_user_blk_start(VirtIODevice *vdev) return ret; } - ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true); + ret = vhost_dev_assign_guest_notifiers(&s->dev, vdev, s->dev.nvqs); if (ret < 0) { - error_report("Error binding guest notifier: %d", -ret); goto err_host_notifiers; } @@ -163,7 +160,7 @@ static int vhost_user_blk_start(VirtIODevice *vdev) return ret; err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); + vhost_dev_drop_guest_notifiers(&s->dev, vdev, s->dev.nvqs); err_host_notifiers: vhost_dev_disable_notifiers(&s->dev, vdev); return ret; @@ -172,17 +169,15 @@ err_host_notifiers: static void vhost_user_blk_stop(VirtIODevice *vdev) { VHostUserBlk *s = VHOST_USER_BLK(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { return; } vhost_dev_stop(&s->dev, vdev); - ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); + ret = vhost_dev_drop_guest_notifiers(&s->dev, vdev, s->dev.nvqs); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d", ret); return; diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 6b82803..c13b444 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -303,19 +303,15 @@ static void vhost_net_stop_one(struct vhost_net *net, int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); - VirtioBusState *vbus = VIRTIO_BUS(qbus); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); + struct vhost_net *net; int r, e, i; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(dev)) { error_report("binding does not support guest notifiers"); return -ENOSYS; } for (i = 0; i < total_queues; i++) { - struct vhost_net *net; - net = get_vhost_net(ncs[i].peer); vhost_net_set_vq_index(net, i * 2); @@ -328,9 +324,13 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, } } - r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); + /* + * Since all the states are handled by one vhost_net device, + * use the first one in array. + */ + net = get_vhost_net(ncs[0].peer); + r = vhost_dev_assign_guest_notifiers(&net->dev, dev, total_queues * 2); if (r < 0) { - error_report("Error binding guest notifier: %d", -r); goto err; } @@ -357,7 +357,8 @@ err_start: while (--i >= 0) { vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); } - e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); + net = get_vhost_net(ncs[0].peer); + e = vhost_dev_drop_guest_notifiers(&net->dev, dev, total_queues * 2); if (e < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e); fflush(stderr); @@ -369,16 +370,19 @@ err: void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, int total_queues) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); - VirtioBusState *vbus = VIRTIO_BUS(qbus); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); + struct vhost_net *net; int i, r; for (i = 0; i < total_queues; i++) { vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); } - r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); + /* + * Since all the states are handled by one vhost_net device, + * use the first one in array. + */ + net = get_vhost_net(ncs[0].peer); + r = vhost_dev_drop_guest_notifiers(&net->dev, dev, total_queues * 2); if (r < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); fflush(stderr); diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c index 8ec49d7..8f51ec0 100644 --- a/hw/scsi/vhost-scsi-common.c +++ b/hw/scsi/vhost-scsi-common.c @@ -29,10 +29,8 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) { int ret, i; VirtIODevice *vdev = VIRTIO_DEVICE(vsc); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { error_report("binding does not support guest notifiers"); return -ENOSYS; } @@ -42,9 +40,8 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) return ret; } - ret = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, true); + ret = vhost_dev_assign_guest_notifiers(&vsc->dev, vdev, vsc->dev.nvqs); if (ret < 0) { - error_report("Error binding guest notifier"); goto err_host_notifiers; } @@ -66,7 +63,7 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) return ret; err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false); + vhost_dev_drop_guest_notifiers(&vsc->dev, vdev, vsc->dev.nvqs); err_host_notifiers: vhost_dev_disable_notifiers(&vsc->dev, vdev); return ret; @@ -75,14 +72,12 @@ err_host_notifiers: void vhost_scsi_common_stop(VHostSCSICommon *vsc) { VirtIODevice *vdev = VIRTIO_DEVICE(vsc); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret = 0; vhost_dev_stop(&vsc->dev, vdev); - if (k->set_guest_notifiers) { - ret = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false); + if (virtio_device_guest_notifiers_initialized(vdev)) { + ret = vhost_dev_drop_guest_notifiers(&vsc->dev, vdev, vsc->dev.nvqs); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d", ret); } diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index 6136768..6b101fc 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -38,12 +38,10 @@ static void vuf_get_config(VirtIODevice *vdev, uint8_t *config) static void vuf_start(VirtIODevice *vdev) { VHostUserFS *fs = VHOST_USER_FS(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; int i; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { error_report("binding does not support guest notifiers"); return; } @@ -54,9 +52,9 @@ static void vuf_start(VirtIODevice *vdev) return; } - ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, true); + ret = vhost_dev_assign_guest_notifiers(&fs->vhost_dev, vdev, + fs->vhost_dev.nvqs); if (ret < 0) { - error_report("Error binding guest notifier: %d", -ret); goto err_host_notifiers; } @@ -79,7 +77,7 @@ static void vuf_start(VirtIODevice *vdev) return; err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false); + vhost_dev_drop_guest_notifiers(&fs->vhost_dev, vdev, fs->vhost_dev.nvqs); err_host_notifiers: vhost_dev_disable_notifiers(&fs->vhost_dev, vdev); } @@ -87,17 +85,16 @@ err_host_notifiers: static void vuf_stop(VirtIODevice *vdev) { VHostUserFS *fs = VHOST_USER_FS(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { return; } vhost_dev_stop(&fs->vhost_dev, vdev); - ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false); + ret = vhost_dev_drop_guest_notifiers(&fs->vhost_dev, vdev, + fs->vhost_dev.nvqs); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d", ret); return; diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 09b6b07..52489dd 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -75,12 +75,10 @@ static int vhost_vsock_set_running(VHostVSock *vsock, int start) static void vhost_vsock_start(VirtIODevice *vdev) { VHostVSock *vsock = VHOST_VSOCK(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; int i; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { error_report("binding does not support guest notifiers"); return; } @@ -91,9 +89,9 @@ static void vhost_vsock_start(VirtIODevice *vdev) return; } - ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, true); + ret = vhost_dev_assign_guest_notifiers(&vsock->vhost_dev, + vdev, vsock->vhost_dev.nvqs); if (ret < 0) { - error_report("Error binding guest notifier: %d", -ret); goto err_host_notifiers; } @@ -123,7 +121,8 @@ static void vhost_vsock_start(VirtIODevice *vdev) err_dev_start: vhost_dev_stop(&vsock->vhost_dev, vdev); err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false); + vhost_dev_drop_guest_notifiers(&vsock->vhost_dev, + vdev, vsock->vhost_dev.nvqs); err_host_notifiers: vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev); } @@ -131,11 +130,9 @@ err_host_notifiers: static void vhost_vsock_stop(VirtIODevice *vdev) { VHostVSock *vsock = VHOST_VSOCK(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; - if (!k->set_guest_notifiers) { + if (!virtio_device_guest_notifiers_initialized(vdev)) { return; } @@ -147,7 +144,8 @@ static void vhost_vsock_stop(VirtIODevice *vdev) vhost_dev_stop(&vsock->vhost_dev, vdev); - ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false); + ret = vhost_dev_drop_guest_notifiers(&vsock->vhost_dev, + vdev, vsock->vhost_dev.nvqs); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d", ret); return; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 01ebe12..fa3da9c 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1419,6 +1419,44 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) virtio_device_release_ioeventfd(vdev); } +/* + * Assign guest notifiers. + * Should be called after vhost_dev_enable_notifiers. + */ +int vhost_dev_assign_guest_notifiers(struct vhost_dev *hdev, + VirtIODevice *vdev, int nvqs) +{ + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + + ret = k->set_guest_notifiers(qbus->parent, nvqs, true); + if (ret < 0) { + error_report("Error binding guest notifier: %d", -ret); + } + + return ret; +} + +/* + * Drop guest notifiers. + * Should be called before vhost_dev_disable_notifiers. + */ +int vhost_dev_drop_guest_notifiers(struct vhost_dev *hdev, + VirtIODevice *vdev, int nvqs) +{ + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + + ret = k->set_guest_notifiers(qbus->parent, nvqs, false); + if (ret < 0) { + error_report("Error reset guest notifier: %d", -ret); + } + + return ret; +} + /* Test and clear event pending status. * Should be called after unmask to avoid losing events. */ diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index b6c8ef5..8a95618 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3812,6 +3812,19 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev) return virtio_bus_ioeventfd_enabled(vbus); } +/* + * Check if set_guest_notifiers() method is set by the init routine. + * Return true if yes, otherwise return false. + */ +bool virtio_device_guest_notifiers_initialized(VirtIODevice *vdev) +{ + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + + return k->set_guest_notifiers; +} + + static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_DEVICE, .parent = TYPE_DEVICE, diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 085450c..4d0d2e2 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -100,6 +100,10 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_assign_guest_notifiers(struct vhost_dev *hdev, + VirtIODevice *vdev, int nvqs); +int vhost_dev_drop_guest_notifiers(struct vhost_dev *hdev, + VirtIODevice *vdev, int nvqs); /* Test and clear masked event pending status. * Should be called after unmask to avoid losing events. diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b69d517..d9a3d72 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -323,6 +323,7 @@ void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, VirtIOHandleAIOOutput handle_output); VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); VirtQueue *virtio_vector_next_queue(VirtQueue *vq); +bool virtio_device_guest_notifiers_initialized(VirtIODevice *vdev); static inline void virtio_add_feature(uint64_t *features, unsigned int fbit) { -- 2.7.4