diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-07-15 15:06:17 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-07-15 15:06:17 +0100 |
commit | 2c65ebe6465618ca159398dfb15d9118ae0fd99f (patch) | |
tree | ced93e720b3d0011a5b97b6d255d49f99d281890 /hw | |
parent | 0e16297461264b3ea8f7282d1195cf53aa8a707c (diff) | |
parent | 5b2ffbe4d99843fd8305c573a100047a8c962327 (diff) |
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request
# gpg: Signature made Tue 15 Jul 2014 14:49:01 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>"
* remotes/stefanha/tags/block-pull-request:
virtio-blk: dataplane: notify guest as a batch
virtio-blk: data-plane: fix save/set .complete_request in start
linux-aio: Fix laio resource leak
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/block/dataplane/virtio-blk.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 227bb15efc..d6ba65ca23 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -34,6 +34,7 @@ struct VirtIOBlockDataPlane { VirtIODevice *vdev; Vring vring; /* virtqueue vring */ EventNotifier *guest_notifier; /* irq */ + QEMUBH *bh; /* bh for guest notification */ /* Note that these EventNotifiers are assigned by value. This is * fine as long as you do not call event_notifier_cleanup on them @@ -61,13 +62,28 @@ static void notify_guest(VirtIOBlockDataPlane *s) event_notifier_set(s->guest_notifier); } +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(&req->dev->dataplane->vring, &req->elem, req->qiov.size + sizeof(*req->in)); - notify_guest(req->dev->dataplane); + + /* 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) @@ -125,7 +141,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, Error **errp) { VirtIOBlockDataPlane *s; - VirtIOBlock *vblk = VIRTIO_BLK(vdev); Error *local_err = NULL; BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); @@ -173,13 +188,12 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, s->iothread = &s->internal_iothread_obj; } s->ctx = iothread_get_aio_context(s->iothread); + s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); error_setg(&s->blocker, "block device is in use by data plane"); bdrv_op_block_all(blk->conf.bs, s->blocker); *dataplane = s; - s->saved_complete_request = vblk->complete_request; - vblk->complete_request = complete_request_vring; } /* Context: QEMU global mutex held */ @@ -193,6 +207,7 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) bdrv_op_unblock_all(s->blk->conf.bs, s->blocker); error_free(s->blocker); object_unref(OBJECT(s->iothread)); + qemu_bh_delete(s->bh); g_free(s); } @@ -201,6 +216,7 @@ 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; if (s->started) { @@ -234,6 +250,9 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) } 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; s->started = true; trace_virtio_blk_data_plane_start(s); |