From 4289ffd14c43be2d6c9d95b0812ee080dd26b36e Mon Sep 17 00:00:00 2001
Message-Id: <4289ffd14c43be2d6c9d95b0812ee080dd26b36e.1357726992.git.minovotn@redhat.com>
In-Reply-To: <4f8efce613a639a3c1e3022c521d6c70b7154de8.1357726992.git.minovotn@redhat.com>
References: <4f8efce613a639a3c1e3022c521d6c70b7154de8.1357726992.git.minovotn@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 2 Jan 2013 15:02:38 +0100
Subject: [PATCH 15/16] virtio-blk: add x-data-plane=on|off performance
 feature

RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: <1357138959-1918-16-git-send-email-stefanha@redhat.com>
Patchwork-id: 45528
O-Subject: [RHEL6.4 qemu-kvm PATCH v5 15/16] virtio-blk: add x-data-plane=on|off performance feature
Bugzilla: 877836
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Asias He <asias@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

The virtio-blk-data-plane feature is easy to integrate into
hw/virtio-blk.c.  The data plane can be started and stopped similar to
vhost-net.

Users can take advantage of the virtio-blk-data-plane feature using the
new -device virtio-blk-pci,x-data-plane=on property.

The x-data-plane name was chosen because at this stage the feature is
experimental and likely to see changes in the future.

If the VM configuration does not support virtio-blk-data-plane an error
message is printed.  Although we could fall back to regular virtio-blk,
I prefer the explicit approach since it prompts the user to fix their
configuration if they want the performance benefit of
virtio-blk-data-plane.

Limitations:
 * Only format=raw is supported
 * Live migration is not supported
 * Block jobs, hot unplug, and other operations fail with -EBUSY
 * I/O throttling limits are ignored
 * Only Linux hosts are supported due to Linux AIO usage

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/virtio-blk.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-pci.c |  4 ++++
 2 files changed, 58 insertions(+)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/virtio-blk.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-pci.c |  4 ++++
 2 files changed, 58 insertions(+)

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index d6e8423..5ea0ddb 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -15,6 +15,9 @@
 #include "qemu-error.h"
 #include "trace.h"
 #include "virtio-blk.h"
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+#include "hw/dataplane/virtio-blk.h"
+#endif
 #include "scsi-defs.h"
 #ifdef __linux__
 # include <scsi/sg.h>
@@ -31,6 +34,9 @@ typedef struct VirtIOBlock
     VirtIOBlkConf *blk;
     unsigned short sector_mask;
     DeviceState *qdev;
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    VirtIOBlockDataPlane *dataplane;
+#endif
 } VirtIOBlock;
 
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -422,6 +428,16 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
         .old_bs = NULL,
     };
 
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    /* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
+     * dataplane here instead of waiting for .set_status().
+     */
+    if (s->dataplane) {
+        virtio_blk_data_plane_start(s->dataplane);
+        return;
+    }
+#endif
+
     while ((req = virtio_blk_get_request(s))) {
         virtio_blk_handle_request(req, &mrb);
     }
@@ -476,6 +492,14 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, RunState state)
 
 static void virtio_blk_reset(VirtIODevice *vdev)
 {
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    VirtIOBlock *s = to_virtio_blk(vdev);
+
+    if (s->dataplane) {
+        virtio_blk_data_plane_stop(s->dataplane);
+    }
+#endif
+
     /*
      * This should cancel pending requests, but can't do nicely until there
      * are per-device request lists.
@@ -527,6 +551,17 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
     return features;
 }
 
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
+{
+    VirtIOBlock *s = to_virtio_blk(vdev);
+
+    if (s->dataplane && !(status & VIRTIO_CONFIG_S_DRIVER)) {
+        virtio_blk_data_plane_stop(s->dataplane);
+    }
+}
+#endif
+
 static void virtio_blk_save(QEMUFile *f, void *opaque)
 {
     VirtIOBlock *s = opaque;
@@ -621,6 +656,9 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 
     s->vdev.get_config = virtio_blk_update_config;
     s->vdev.get_features = virtio_blk_get_features;
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    s->vdev.set_status = virtio_blk_set_status;
+#endif
     s->vdev.reset = virtio_blk_reset;
     s->bs = blk->conf.bs;
     s->conf = &blk->conf;
@@ -631,11 +669,22 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
     bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
 
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    if (!virtio_blk_data_plane_create(&s->vdev, blk, &s->dataplane)) {
+        virtio_cleanup(&s->vdev);
+        return NULL;
+    }
+#endif
 
     qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
     s->qdev = dev;
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    if (s->dataplane) {
+        register_device_unmigratable(dev, "virtio-blk", s);
+    }
+#endif
     bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
     s->bs->buffer_alignment = s->conf->logical_block_size;
 
@@ -648,6 +697,11 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 void virtio_blk_exit(VirtIODevice *vdev)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
+
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    virtio_blk_data_plane_destroy(s->dataplane);
+    s->dataplane = NULL;
+#endif
     unregister_savevm(s->qdev, "virtio-blk", s);
     virtio_cleanup(vdev);
 }
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index cdcc14d..28c48c7 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -992,6 +992,10 @@ static PCIDeviceInfo virtio_info[] = {
             DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
             DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
                             VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+            DEFINE_PROP_BIT("x-data-plane", VirtIOPCIProxy, blk.data_plane, 0,
+                            false),
+#endif
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
             DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
             DEFINE_PROP_END_OF_LIST(),
-- 
1.7.11.7