diff options
Diffstat (limited to 'hw/block/dataplane/virtio-blk.c')
-rw-r--r-- | hw/block/dataplane/virtio-blk.c | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 704a763603..d1f9f63eaf 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -68,9 +68,7 @@ static void notify_guest_bh(void *opaque) unsigned i = j + ctzl(bits); VirtQueue *vq = virtio_get_queue(s->vdev, i); - if (virtio_should_notify(s->vdev, vq)) { - event_notifier_set(virtio_queue_get_guest_notifier(vq)); - } + virtio_notify_irqfd(s->vdev, vq); bits &= bits - 1; /* clear right-most bit */ } @@ -88,23 +86,28 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, *dataplane = NULL; - if (!conf->iothread) { - return; - } + if (conf->iothread) { + if (!k->set_guest_notifiers || !k->ioeventfd_assign) { + error_setg(errp, + "device is incompatible with iothread " + "(transport does not support notifiers)"); + return; + } + if (!virtio_device_ioeventfd_enabled(vdev)) { + error_setg(errp, "ioeventfd is required for iothread"); + return; + } - /* Don't try if transport does not support notifiers. */ - if (!k->set_guest_notifiers || !k->ioeventfd_started) { - error_setg(errp, - "device is incompatible with dataplane " - "(transport does not support notifiers)"); - return; + /* If dataplane is (re-)enabled while the guest is running there could + * be block jobs that can conflict. + */ + if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { + error_prepend(errp, "cannot start virtio-blk dataplane: "); + return; + } } - - /* If dataplane is (re-)enabled while the guest is running there could be - * block jobs that can conflict. - */ - if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { - error_prepend(errp, "cannot start dataplane thread: "); + /* Don't try if transport does not support notifiers. */ + if (!virtio_device_ioeventfd_enabled(vdev)) { return; } @@ -112,9 +115,13 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, s->vdev = vdev; s->conf = conf; - s->iothread = conf->iothread; - object_ref(OBJECT(s->iothread)); - s->ctx = iothread_get_aio_context(s->iothread); + if (conf->iothread) { + s->iothread = conf->iothread; + object_ref(OBJECT(s->iothread)); + s->ctx = iothread_get_aio_context(s->iothread); + } else { + s->ctx = qemu_get_aio_context(); + } s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); s->batch_notify_vqs = bitmap_new(conf->num_queues); @@ -124,14 +131,19 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, /* Context: QEMU global mutex held */ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) { + VirtIOBlock *vblk; + if (!s) { return; } - virtio_blk_data_plane_stop(s); + vblk = VIRTIO_BLK(s->vdev); + assert(!vblk->dataplane_started); g_free(s->batch_notify_vqs); qemu_bh_delete(s->bh); - object_unref(OBJECT(s->iothread)); + if (s->iothread) { + object_unref(OBJECT(s->iothread)); + } g_free(s); } @@ -147,17 +159,18 @@ static void virtio_blk_data_plane_handle_output(VirtIODevice *vdev, } /* Context: QEMU global mutex held */ -void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) +int virtio_blk_data_plane_start(VirtIODevice *vdev) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); + VirtIOBlock *vblk = VIRTIO_BLK(vdev); + VirtIOBlockDataPlane *s = vblk->dataplane; + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vblk))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); unsigned i; unsigned nvqs = s->conf->num_queues; int r; if (vblk->dataplane_started || s->starting) { - return; + return 0; } s->starting = true; @@ -204,20 +217,22 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) virtio_blk_data_plane_handle_output); } aio_context_release(s->ctx); - return; + return 0; fail_guest_notifiers: vblk->dataplane_disabled = true; s->starting = false; vblk->dataplane_started = true; + return -ENOSYS; } /* Context: QEMU global mutex held */ -void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) +void virtio_blk_data_plane_stop(VirtIODevice *vdev) { - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); + VirtIOBlock *vblk = VIRTIO_BLK(vdev); + VirtIOBlockDataPlane *s = vblk->dataplane; + BusState *qbus = qdev_get_parent_bus(DEVICE(vblk)); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); unsigned i; unsigned nvqs = s->conf->num_queues; |