@@ -54,11 +54,28 @@ static void virtio_blk_batch_notify_bh(void *opaque)
{
VirtIOBlock *s = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(s);
+ unsigned nvqs = s->conf.num_queues;
+ unsigned long bitmap[BITS_TO_LONGS(nvqs)];
+ unsigned j;
- if (s->dataplane_started && !s->dataplane_disabled) {
- virtio_blk_data_plane_notify(s->dataplane, s->vq);
- } else {
- virtio_notify(vdev, s->vq);
+ memcpy(bitmap, s->batch_notify_vqs, sizeof(bitmap));
+ memset(s->batch_notify_vqs, 0, sizeof(bitmap));
+
+ for (j = 0; j < nvqs; j += BITS_PER_LONG) {
+ unsigned long bits = bitmap[j];
+
+ while (bits != 0) {
+ unsigned i = j + ctzl(bits);
+ VirtQueue *vq = virtio_get_queue(vdev, i);
+
+ if (s->dataplane_started && !s->dataplane_disabled) {
+ virtio_blk_data_plane_notify(s->dataplane, vq);
+ } else {
+ virtio_notify(vdev, vq);
+ }
+
+ bits &= bits - 1; /* clear right-most bit */
+ }
}
}
@@ -97,6 +114,8 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
stb_p(&req->in->status, status);
virtqueue_push(req->vq, &req->elem, req->in_len);
+
+ set_bit(virtio_queue_get_id(req->vq), s->batch_notify_vqs);
qemu_bh_schedule(s->batch_notify_bh);
}
@@ -940,6 +959,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
return;
}
+ s->batch_notify_vqs = bitmap_new(conf->num_queues);
blk_add_aio_context_notifier(s->blk, virtio_blk_attached_aio_context,
virtio_blk_detach_aio_context, s);
virtio_blk_attached_aio_context(blk_get_aio_context(s->blk), s);
@@ -961,6 +981,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
blk_remove_aio_context_notifier(s->blk, virtio_blk_attached_aio_context,
virtio_blk_detach_aio_context, s);
virtio_blk_detach_aio_context(s);
+ g_free(s->batch_notify_vqs);
virtio_blk_data_plane_destroy(s->dataplane);
s->dataplane = NULL;
qemu_del_vm_change_state_handler(s->change);
@@ -51,6 +51,7 @@ typedef struct VirtIOBlock {
void *rq;
QEMUBH *bh;
QEMUBH *batch_notify_bh;
+ unsigned long *batch_notify_vqs;
VirtIOBlkConf conf;
unsigned short sector_mask;
bool original_wce;
The batch notification BH needs to know which virtqueues to notify when multiqueue is enabled. Use a bitmap to track the virtqueues with pending notifications. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> --- hw/block/virtio-blk.c | 29 +++++++++++++++++++++++++---- include/hw/virtio/virtio-blk.h | 1 + 2 files changed, 26 insertions(+), 4 deletions(-)