virtio: Clarify MR transaction optimization
The device model batching its ioeventfds in a single MR transaction is an optimization. Clarify this in virtio-scsi, virtio-blk and generic virtio code. Also clarify that the transaction must commit before closing ioeventfds so that no one is tempted to merge the loops in the start functions error path and in the stop functions. Signed-off-by: Greg Kurz <groug@kaod.org> Message-Id: <162125799728.1394228.339855768563326832.stgit@bahia.lan> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
3909c07945
commit
9cf4fd872d
|
@ -198,6 +198,10 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
|
|||
goto fail_guest_notifiers;
|
||||
}
|
||||
|
||||
/*
|
||||
* Batch all the host notifiers in a single transaction to avoid
|
||||
* quadratic time complexity in address_space_update_ioeventfds().
|
||||
*/
|
||||
memory_region_transaction_begin();
|
||||
|
||||
/* Set up virtqueue notify */
|
||||
|
@ -211,6 +215,10 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
|
|||
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* The transaction expects the ioeventfds to be open when it
|
||||
* commits. Do it now, before the cleanup loop.
|
||||
*/
|
||||
memory_region_transaction_commit();
|
||||
|
||||
while (j--) {
|
||||
|
@ -330,12 +338,20 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
|
|||
|
||||
aio_context_release(s->ctx);
|
||||
|
||||
/*
|
||||
* Batch all the host notifiers in a single transaction to avoid
|
||||
* quadratic time complexity in address_space_update_ioeventfds().
|
||||
*/
|
||||
memory_region_transaction_begin();
|
||||
|
||||
for (i = 0; i < nvqs; i++) {
|
||||
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* The transaction expects the ioeventfds to be open when it
|
||||
* commits. Do it now, before the cleanup loop.
|
||||
*/
|
||||
memory_region_transaction_commit();
|
||||
|
||||
for (i = 0; i < nvqs; i++) {
|
||||
|
|
|
@ -152,6 +152,10 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
|
|||
goto fail_guest_notifiers;
|
||||
}
|
||||
|
||||
/*
|
||||
* Batch all the host notifiers in a single transaction to avoid
|
||||
* quadratic time complexity in address_space_update_ioeventfds().
|
||||
*/
|
||||
memory_region_transaction_begin();
|
||||
|
||||
rc = virtio_scsi_set_host_notifier(s, vs->ctrl_vq, 0);
|
||||
|
@ -198,6 +202,10 @@ fail_host_notifiers:
|
|||
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* The transaction expects the ioeventfds to be open when it
|
||||
* commits. Do it now, before the cleanup loop.
|
||||
*/
|
||||
memory_region_transaction_commit();
|
||||
|
||||
for (i = 0; i < vq_init_count; i++) {
|
||||
|
@ -238,12 +246,20 @@ void virtio_scsi_dataplane_stop(VirtIODevice *vdev)
|
|||
|
||||
blk_drain_all(); /* ensure there are no in-flight requests */
|
||||
|
||||
/*
|
||||
* Batch all the host notifiers in a single transaction to avoid
|
||||
* quadratic time complexity in address_space_update_ioeventfds().
|
||||
*/
|
||||
memory_region_transaction_begin();
|
||||
|
||||
for (i = 0; i < vs->conf.num_queues + 2; i++) {
|
||||
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* The transaction expects the ioeventfds to be open when it
|
||||
* commits. Do it now, before the cleanup loop.
|
||||
*/
|
||||
memory_region_transaction_commit();
|
||||
|
||||
for (i = 0; i < vs->conf.num_queues + 2; i++) {
|
||||
|
|
|
@ -3728,6 +3728,10 @@ static int virtio_device_start_ioeventfd_impl(VirtIODevice *vdev)
|
|||
VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
int i, n, r, err;
|
||||
|
||||
/*
|
||||
* Batch all the host notifiers in a single transaction to avoid
|
||||
* quadratic time complexity in address_space_update_ioeventfds().
|
||||
*/
|
||||
memory_region_transaction_begin();
|
||||
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||
VirtQueue *vq = &vdev->vq[n];
|
||||
|
@ -3766,6 +3770,10 @@ assign_error:
|
|||
r = virtio_bus_set_host_notifier(qbus, n, false);
|
||||
assert(r >= 0);
|
||||
}
|
||||
/*
|
||||
* The transaction expects the ioeventfds to be open when it
|
||||
* commits. Do it now, before the cleanup loop.
|
||||
*/
|
||||
memory_region_transaction_commit();
|
||||
|
||||
while (--i >= 0) {
|
||||
|
@ -3790,6 +3798,10 @@ static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
|
|||
VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
int n, r;
|
||||
|
||||
/*
|
||||
* Batch all the host notifiers in a single transaction to avoid
|
||||
* quadratic time complexity in address_space_update_ioeventfds().
|
||||
*/
|
||||
memory_region_transaction_begin();
|
||||
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||
VirtQueue *vq = &vdev->vq[n];
|
||||
|
@ -3801,6 +3813,10 @@ static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
|
|||
r = virtio_bus_set_host_notifier(qbus, n, false);
|
||||
assert(r >= 0);
|
||||
}
|
||||
/*
|
||||
* The transaction expects the ioeventfds to be open when it
|
||||
* commits. Do it now, before the cleanup loop.
|
||||
*/
|
||||
memory_region_transaction_commit();
|
||||
|
||||
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||
|
|
Loading…
Reference in New Issue