Patchwork [07/16] virtio-scsi: Start/stop vhost

login
register
mail settings
Submitter Zhiyong Wu
Date April 19, 2012, 2:39 a.m.
Message ID <1334803149-27379-8-git-send-email-zwu.kernel@gmail.com>
Download mbox | patch
Permalink /patch/153627/
State New
Headers show

Comments

Zhiyong Wu - April 19, 2012, 2:39 a.m.
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

This patch starts and stops vhost as the virtio device transitions
through its status phases.  Vhost can only be started once the guest
reports its driver has successfully initialized, which means the
virtqueues have been set up by the guest.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
---
 hw/virtio-scsi.c |   44 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 43 insertions(+), 1 deletions(-)

Patch

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 5c74523..85170d3 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -138,7 +138,6 @@  typedef struct {
     uint32_t sense_size;
     uint32_t cdb_size;
     int resetting;
-    struct vhost_virtqueue vhost_vqs[1];
     bool vhost_started;
     VHostSCSI *vhost_scsi;
 } VirtIOSCSI;
@@ -586,6 +585,42 @@  static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .load_request = virtio_scsi_load_request,
 };
 
+static bool virtio_scsi_started(VirtIOSCSI *s, uint8_t val)
+{
+    return (val & VIRTIO_CONFIG_S_DRIVER_OK) && s->vdev.vm_running;
+}
+
+static void virtio_scsi_set_status(VirtIODevice *vdev, uint8_t val)
+{
+    VirtIOSCSI *s = to_virtio_scsi(vdev);
+    bool start = virtio_scsi_started(s, val);
+
+    if (s->vhost_started == start) {
+        return;
+    }
+
+    if (start) {
+        int ret;
+
+        if (!vhost_dev_query(&s->vhost_scsi, vdev)) {
+            return;
+        }
+
+        ret = virtio_scsi_vhost_start(s);
+        if (ret < 0) {
+            error_report("virtio-scsi: unable to start vhost: %s\n",
+                         strerror(-ret));
+
+            /* There is no userspace virtio-scsi fallback so exit */
+            exit(1);
+        }
+    } else {
+        virtio_scsi_vhost_stop(s);
+    }
+
+    s->vhost_started = start;
+}
+
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 {
     VirtIOSCSI *s;
@@ -605,6 +640,9 @@  VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
     s->vdev.set_config = virtio_scsi_set_config;
     s->vdev.get_features = virtio_scsi_get_features;
     s->vdev.reset = virtio_scsi_reset;
+    if (s->vhost_scsi) {
+        s->vdev.set_status = virtio_scsi_set_status;
+    }
 
     s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_ctrl);
@@ -628,6 +666,10 @@  void virtio_scsi_exit(VirtIODevice *vdev)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
     unregister_savevm(s->qdev, "virtio-scsi", s);
+
+    /* This will stop vhost backend if appropriate. */
+    virtio_scsi_set_status(vdev, 0);
+
     vhost_dev_cleanup(&s->vhost_scsi);
     virtio_cleanup(vdev);
 }