From 03de2f527499ae0c6d16a379665d072345254f2c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 14 Feb 2016 18:17:09 +0100 Subject: [PATCH] virtio-blk: do not use vring in dataplane Signed-off-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Fam Zheng Acked-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 112 +++++----------------------------------- hw/block/dataplane/virtio-blk.h | 1 + hw/block/virtio-blk.c | 49 +++--------------- include/hw/virtio/virtio-blk.h | 3 -- 4 files changed, 19 insertions(+), 146 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index cc521c173c..36f3d2b813 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -18,8 +18,6 @@ #include "qemu/thread.h" #include "qemu/error-report.h" #include "hw/virtio/virtio-access.h" -#include "hw/virtio/dataplane/vring.h" -#include "hw/virtio/dataplane/vring-accessors.h" #include "sysemu/block-backend.h" #include "hw/virtio/virtio-blk.h" #include "virtio-blk.h" @@ -35,7 +33,7 @@ struct VirtIOBlockDataPlane { VirtIOBlkConf *conf; VirtIODevice *vdev; - Vring vring; /* virtqueue vring */ + VirtQueue *vq; /* virtqueue vring */ EventNotifier *guest_notifier; /* irq */ QEMUBH *bh; /* bh for guest notification */ @@ -48,94 +46,26 @@ struct VirtIOBlockDataPlane { */ IOThread *iothread; AioContext *ctx; - EventNotifier host_notifier; /* doorbell */ /* Operation blocker on BDS */ Error *blocker; - void (*saved_complete_request)(struct VirtIOBlockReq *req, - unsigned char status); }; /* Raise an interrupt to signal guest, if necessary */ -static void notify_guest(VirtIOBlockDataPlane *s) +void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s) { - if (!vring_should_notify(s->vdev, &s->vring)) { - return; - } - - event_notifier_set(s->guest_notifier); + qemu_bh_schedule(s->bh); } static void notify_guest_bh(void *opaque) { VirtIOBlockDataPlane *s = opaque; - notify_guest(s); -} - -static void complete_request_vring(VirtIOBlockReq *req, unsigned char status) -{ - VirtIOBlockDataPlane *s = req->dev->dataplane; - stb_p(&req->in->status, status); - - vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem, req->in_len); - - /* Suppress notification to guest by BH and its scheduled - * flag because requests are completed as a batch after io - * plug & unplug is introduced, and the BH can still be - * executed in dataplane aio context even after it is - * stopped, so needn't worry about notification loss with BH. - */ - qemu_bh_schedule(s->bh); -} - -static void handle_notify(EventNotifier *e) -{ - VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane, - host_notifier); - VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); - - event_notifier_test_and_clear(&s->host_notifier); - blk_io_plug(s->conf->conf.blk); - for (;;) { - MultiReqBuffer mrb = {}; - - /* Disable guest->host notifies to avoid unnecessary vmexits */ - vring_disable_notification(s->vdev, &s->vring); - - for (;;) { - VirtIOBlockReq *req = vring_pop(s->vdev, &s->vring, - sizeof(VirtIOBlockReq)); - - if (req == NULL) { - break; /* no more requests */ - } - - virtio_blk_init_request(vblk, req); - trace_virtio_blk_data_plane_process_request(s, req->elem.out_num, - req->elem.in_num, - req->elem.index); - - virtio_blk_handle_request(req, &mrb); - } - - if (mrb.num_reqs) { - virtio_blk_submit_multireq(s->conf->conf.blk, &mrb); - } - - if (likely(!vring_more_avail(s->vdev, &s->vring))) { /* vring emptied */ - /* Re-enable guest->host notifies and stop processing the vring. - * But if the guest has snuck in more descriptors, keep processing. - */ - vring_enable_notification(s->vdev, &s->vring); - if (!vring_more_avail(s->vdev, &s->vring)) { - break; - } - } else { /* fatal error */ - break; - } + if (!virtio_should_notify(s->vdev, s->vq)) { + return; } - blk_io_unplug(s->conf->conf.blk); + + event_notifier_set(s->guest_notifier); } static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s) @@ -260,7 +190,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); - VirtQueue *vq; int r; if (vblk->dataplane_started || s->starting) { @@ -268,11 +197,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) } s->starting = true; - - vq = virtio_get_queue(s->vdev, 0); - if (!vring_setup(&s->vring, s->vdev, 0)) { - goto fail_vring; - } + s->vq = virtio_get_queue(s->vdev, 0); /* Set up guest notifier (irq) */ r = k->set_guest_notifiers(qbus->parent, 1, true); @@ -281,7 +206,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) "ensure -enable-kvm is set\n", r); goto fail_guest_notifiers; } - s->guest_notifier = virtio_queue_get_guest_notifier(vq); + s->guest_notifier = virtio_queue_get_guest_notifier(s->vq); /* Set up virtqueue notify */ r = k->set_host_notifier(qbus->parent, 0, true); @@ -289,10 +214,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r); goto fail_host_notifier; } - s->host_notifier = *virtio_queue_get_host_notifier(vq); - - s->saved_complete_request = vblk->complete_request; - vblk->complete_request = complete_request_vring; s->starting = false; vblk->dataplane_started = true; @@ -301,20 +222,17 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) blk_set_aio_context(s->conf->conf.blk, s->ctx); /* Kick right away to begin processing requests already in vring */ - event_notifier_set(virtio_queue_get_host_notifier(vq)); + event_notifier_set(virtio_queue_get_host_notifier(s->vq)); /* Get this show started by hooking up our callbacks */ aio_context_acquire(s->ctx); - aio_set_event_notifier(s->ctx, &s->host_notifier, true, - handle_notify); + virtio_queue_aio_set_host_notifier_handler(s->vq, s->ctx, true, true); aio_context_release(s->ctx); return; fail_host_notifier: k->set_guest_notifiers(qbus->parent, 1, false); fail_guest_notifiers: - vring_teardown(&s->vring, s->vdev, 0); - fail_vring: s->disabled = true; s->starting = false; vblk->dataplane_started = true; @@ -338,24 +256,18 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) return; } s->stopping = true; - vblk->complete_request = s->saved_complete_request; trace_virtio_blk_data_plane_stop(s); aio_context_acquire(s->ctx); /* Stop notifications for new requests from guest */ - aio_set_event_notifier(s->ctx, &s->host_notifier, true, NULL); + virtio_queue_aio_set_host_notifier_handler(s->vq, s->ctx, false, false); /* Drain and switch bs back to the QEMU main loop */ blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context()); aio_context_release(s->ctx); - /* Sync vring state back to virtqueue so that non-dataplane request - * processing can continue when we disable the host notifier below. - */ - vring_teardown(&s->vring, s->vdev, 0); - k->set_host_notifier(qbus->parent, 0, false); /* Clean up guest notifier (irq) */ diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h index c88d40e72c..0714c11a2b 100644 --- a/hw/block/dataplane/virtio-blk.h +++ b/hw/block/dataplane/virtio-blk.h @@ -26,5 +26,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s); void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s); void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s); void virtio_blk_data_plane_drain(VirtIOBlockDataPlane *s); +void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s); #endif /* HW_DATAPLANE_VIRTIO_BLK_H */ diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index e04c8f59fd..cb710f16fa 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -21,7 +21,6 @@ #include "sysemu/blockdev.h" #include "hw/virtio/virtio-blk.h" #include "dataplane/virtio-blk.h" -#include "migration/migration.h" #include "block/scsi.h" #ifdef __linux__ # include @@ -45,8 +44,7 @@ void virtio_blk_free_request(VirtIOBlockReq *req) } } -static void virtio_blk_complete_request(VirtIOBlockReq *req, - unsigned char status) +static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) { VirtIOBlock *s = req->dev; VirtIODevice *vdev = VIRTIO_DEVICE(s); @@ -55,12 +53,11 @@ static void virtio_blk_complete_request(VirtIOBlockReq *req, stb_p(&req->in->status, status); virtqueue_push(s->vq, &req->elem, req->in_len); - virtio_notify(vdev, s->vq); -} - -static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) -{ - req->dev->complete_request(req, status); + if (s->dataplane) { + virtio_blk_data_plane_notify(s->dataplane); + } else { + virtio_notify(vdev, s->vq); + } } static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, @@ -852,36 +849,6 @@ static const BlockDevOps virtio_block_ops = { .resize_cb = virtio_blk_resize, }; -/* Disable dataplane thread during live migration since it does not - * update the dirty memory bitmap yet. - */ -static void virtio_blk_migration_state_changed(Notifier *notifier, void *data) -{ - VirtIOBlock *s = container_of(notifier, VirtIOBlock, - migration_state_notifier); - MigrationState *mig = data; - Error *err = NULL; - - if (migration_in_setup(mig)) { - if (!s->dataplane) { - return; - } - virtio_blk_data_plane_destroy(s->dataplane); - s->dataplane = NULL; - } else if (migration_has_finished(mig) || - migration_has_failed(mig)) { - if (s->dataplane) { - return; - } - blk_drain_all(); /* complete in-flight non-dataplane requests */ - virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->conf, - &s->dataplane, &err); - if (err != NULL) { - error_report_err(err); - } - } -} - static void virtio_blk_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -916,15 +883,12 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1; s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output); - s->complete_request = virtio_blk_complete_request; virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err); if (err != NULL) { error_propagate(errp, err); virtio_cleanup(vdev); return; } - s->migration_state_notifier.notify = virtio_blk_migration_state_changed; - add_migration_state_change_notifier(&s->migration_state_notifier); s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); register_savevm(dev, "virtio-blk", virtio_blk_id++, 2, @@ -940,7 +904,6 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOBlock *s = VIRTIO_BLK(dev); - remove_migration_state_change_notifier(&s->migration_state_notifier); virtio_blk_data_plane_destroy(s->dataplane); s->dataplane = NULL; qemu_del_vm_change_state_handler(s->change); diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index 781969d752..ae84d92107 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -53,9 +53,6 @@ typedef struct VirtIOBlock { unsigned short sector_mask; bool original_wce; VMChangeStateEntry *change; - /* Function to push to vq and notify guest */ - void (*complete_request)(struct VirtIOBlockReq *req, unsigned char status); - Notifier migration_state_notifier; bool dataplane_started; struct VirtIOBlockDataPlane *dataplane; } VirtIOBlock; -- 2.11.4.GIT