get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/812236/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 812236,
    "url": "http://patchwork.ozlabs.org/api/patches/812236/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1505202976-1784-3-git-send-email-changpeng.liu@intel.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1505202976-1784-3-git-send-email-changpeng.liu@intel.com>",
    "list_archive_url": null,
    "date": "2017-09-12T07:56:14",
    "name": "[v3,2/4] vhost-user-blk: introduce a new vhost-user-blk host device",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "315120abcc83539d124fbeb1d813571df741211a",
    "submitter": {
        "id": 71275,
        "url": "http://patchwork.ozlabs.org/api/people/71275/?format=api",
        "name": "Liu, Changpeng",
        "email": "changpeng.liu@intel.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1505202976-1784-3-git-send-email-changpeng.liu@intel.com/mbox/",
    "series": [
        {
            "id": 2447,
            "url": "http://patchwork.ozlabs.org/api/series/2447/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2447",
            "date": "2017-09-12T07:56:15",
            "name": "*** Introduce a new vhost-user-blk host device to Qemu ***",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/2447/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/812236/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/812236/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xrKWV4nzQz9s4q\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 11 Sep 2017 17:37:10 +1000 (AEST)",
            "from localhost ([::1]:55949 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1drJHI-0001FB-OP\n\tfor incoming@patchwork.ozlabs.org; Mon, 11 Sep 2017 03:37:08 -0400",
            "from eggs.gnu.org ([2001:4830:134:3::10]:43364)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <changpeng.liu@intel.com>) id 1drJGV-0001DV-R0\n\tfor qemu-devel@nongnu.org; Mon, 11 Sep 2017 03:36:22 -0400",
            "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <changpeng.liu@intel.com>) id 1drJGT-0007eI-8S\n\tfor qemu-devel@nongnu.org; Mon, 11 Sep 2017 03:36:19 -0400",
            "from mga05.intel.com ([192.55.52.43]:18824)\n\tby eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <changpeng.liu@intel.com>)\n\tid 1drJGS-0007cA-Vz\n\tfor qemu-devel@nongnu.org; Mon, 11 Sep 2017 03:36:17 -0400",
            "from orsmga004.jf.intel.com ([10.7.209.38])\n\tby fmsmga105.fm.intel.com with ESMTP; 11 Sep 2017 00:36:14 -0700",
            "from fedora.sh.intel.com ([10.67.112.210])\n\tby orsmga004.jf.intel.com with ESMTP; 11 Sep 2017 00:36:05 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.42,376,1500966000\"; d=\"scan'208\";a=\"127495098\"",
        "From": "Changpeng Liu <changpeng.liu@intel.com>",
        "To": "changpeng.liu@intel.com,\n\tqemu-devel@nongnu.org",
        "Date": "Tue, 12 Sep 2017 15:56:14 +0800",
        "Message-Id": "<1505202976-1784-3-git-send-email-changpeng.liu@intel.com>",
        "X-Mailer": "git-send-email 1.9.3",
        "In-Reply-To": "<1505202976-1784-1-git-send-email-changpeng.liu@intel.com>",
        "References": "<1505202976-1784-1-git-send-email-changpeng.liu@intel.com>",
        "X-detected-operating-system": "by eggs.gnu.org: Genre and OS details not\n\trecognized.",
        "X-Received-From": "192.55.52.43",
        "Subject": "[Qemu-devel] [PATCH v3 2/4] vhost-user-blk: introduce a new\n\tvhost-user-blk host device",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.21",
        "Precedence": "list",
        "List-Id": "<qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Cc": "james.r.harris@intel.com, mst@redhat.com, stefanha@gmail.com,\n\tpbonzini@redhat.com, felipe@nutanix.com, marcandre.lureau@redhat.com",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"
    },
    "content": "This commit introduces a new vhost-user device for block, it uses a\nchardev to connect with the backend, same with Qemu virito-blk device,\nGuest OS still uses the virtio-blk frontend driver.\n\nTo use it, start Qemu with command line like this:\n\nqemu-system-x86_64 \\\n    -chardev socket,id=char0,path=/path/vhost.socket \\\n    -device vhost-user-blk-pci,chardev=char0,num_queues=1, \\\n            bootindex=2... \\\n\nUsers can use different parameters for `num_queues` and `bootindex`.\n\nDifferent with exist Qemu virtio-blk host device, it makes more easy\nfor users to implement their own I/O processing logic, such as all\nuser space I/O stack against hardware block device. It uses the new\nvhost messages(VHOST_USER_GET_CONFIG) to get block virtio config\ninformation from backend process.\n\nSigned-off-by: Changpeng Liu <changpeng.liu@intel.com>\n---\n configure                          |  11 ++\n hw/block/Makefile.objs             |   3 +\n hw/block/vhost-user-blk.c          | 360 +++++++++++++++++++++++++++++++++++++\n hw/virtio/virtio-pci.c             |  55 ++++++\n hw/virtio/virtio-pci.h             |  18 ++\n include/hw/virtio/vhost-user-blk.h |  40 +++++\n 6 files changed, 487 insertions(+)\n create mode 100644 hw/block/vhost-user-blk.c\n create mode 100644 include/hw/virtio/vhost-user-blk.h",
    "diff": "diff --git a/configure b/configure\nindex fd7e3a5..4259833 100755\n--- a/configure\n+++ b/configure\n@@ -310,6 +310,7 @@ tcg=\"yes\"\n \n vhost_net=\"no\"\n vhost_scsi=\"no\"\n+vhost_user_blk=\"no\"\n vhost_vsock=\"no\"\n vhost_user=\"\"\n kvm=\"no\"\n@@ -774,6 +775,7 @@ Linux)\n   kvm=\"yes\"\n   vhost_net=\"yes\"\n   vhost_scsi=\"yes\"\n+  vhost_user_blk=\"yes\"\n   vhost_vsock=\"yes\"\n   QEMU_INCLUDES=\"-I\\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES\"\n   supported_os=\"yes\"\n@@ -1131,6 +1133,10 @@ for opt do\n   ;;\n   --enable-vhost-scsi) vhost_scsi=\"yes\"\n   ;;\n+  --disable-vhost-user-blk) vhost_user_blk=\"no\"\n+  ;;\n+  --enable-vhost-user-blk) vhost_user_blk=\"yes\"\n+  ;;\n   --disable-vhost-vsock) vhost_vsock=\"no\"\n   ;;\n   --enable-vhost-vsock) vhost_vsock=\"yes\"\n@@ -1501,6 +1507,7 @@ disabled with --disable-FEATURE, default is enabled if available:\n   cap-ng          libcap-ng support\n   attr            attr and xattr support\n   vhost-net       vhost-net acceleration support\n+  vhost-user-blk  VM virtio-blk acceleration in user space\n   spice           spice\n   rbd             rados block device (rbd)\n   libiscsi        iscsi support\n@@ -5360,6 +5367,7 @@ echo \"posix_madvise     $posix_madvise\"\n echo \"libcap-ng support $cap_ng\"\n echo \"vhost-net support $vhost_net\"\n echo \"vhost-scsi support $vhost_scsi\"\n+echo \"vhost-user-blk support $vhost_user_blk\"\n echo \"vhost-vsock support $vhost_vsock\"\n echo \"vhost-user support $vhost_user\"\n echo \"Trace backends    $trace_backends\"\n@@ -5767,6 +5775,9 @@ fi\n if test \"$vhost_scsi\" = \"yes\" ; then\n   echo \"CONFIG_VHOST_SCSI=y\" >> $config_host_mak\n fi\n+if test \"$vhost_user_blk\" = \"yes\" -a \"$vhost_user\" = \"yes\"; then\n+  echo \"CONFIG_VHOST_USER_BLK=y\" >> $config_host_mak\n+fi\n if test \"$vhost_net\" = \"yes\" -a \"$vhost_user\" = \"yes\"; then\n   echo \"CONFIG_VHOST_NET_USED=y\" >> $config_host_mak\n fi\ndiff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs\nindex e0ed980..4c19a58 100644\n--- a/hw/block/Makefile.objs\n+++ b/hw/block/Makefile.objs\n@@ -13,3 +13,6 @@ obj-$(CONFIG_SH4) += tc58128.o\n \n obj-$(CONFIG_VIRTIO) += virtio-blk.o\n obj-$(CONFIG_VIRTIO) += dataplane/\n+ifeq ($(CONFIG_VIRTIO),y)\n+obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o\n+endif\ndiff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c\nnew file mode 100644\nindex 0000000..8aa9fa9\n--- /dev/null\n+++ b/hw/block/vhost-user-blk.c\n@@ -0,0 +1,360 @@\n+/*\n+ * vhost-user-blk host device\n+ *\n+ * Copyright IBM, Corp. 2011\n+ * Copyright(C) 2017 Intel Corporation.\n+ *\n+ * Authors:\n+ *  Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>\n+ *  Changpeng Liu <changpeng.liu@intel.com>\n+ *\n+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.\n+ * See the COPYING.LIB file in the top-level directory.\n+ *\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qapi/error.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qemu/typedefs.h\"\n+#include \"qemu/cutils.h\"\n+#include \"qom/object.h\"\n+#include \"hw/qdev-core.h\"\n+#include \"hw/virtio/vhost.h\"\n+#include \"hw/virtio/vhost-user-blk.h\"\n+#include \"hw/virtio/virtio.h\"\n+#include \"hw/virtio/virtio-bus.h\"\n+#include \"hw/virtio/virtio-access.h\"\n+\n+static const int user_feature_bits[] = {\n+    VIRTIO_BLK_F_SIZE_MAX,\n+    VIRTIO_BLK_F_SEG_MAX,\n+    VIRTIO_BLK_F_GEOMETRY,\n+    VIRTIO_BLK_F_BLK_SIZE,\n+    VIRTIO_BLK_F_TOPOLOGY,\n+    VIRTIO_BLK_F_SCSI,\n+    VIRTIO_BLK_F_MQ,\n+    VIRTIO_BLK_F_RO,\n+    VIRTIO_BLK_F_FLUSH,\n+    VIRTIO_BLK_F_BARRIER,\n+    VIRTIO_BLK_F_WCE,\n+    VIRTIO_F_VERSION_1,\n+    VIRTIO_RING_F_INDIRECT_DESC,\n+    VIRTIO_RING_F_EVENT_IDX,\n+    VIRTIO_F_NOTIFY_ON_EMPTY,\n+    VHOST_INVALID_FEATURE_BIT\n+};\n+\n+static void vhost_user_blk_update_config(VirtIODevice *vdev, uint8_t *config)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+\n+    memcpy(config, &s->blkcfg, sizeof(struct virtio_blk_config));\n+}\n+\n+static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+    struct virtio_blk_config *blkcfg = (struct virtio_blk_config *)config;\n+    int ret;\n+\n+    if (blkcfg->wce == s->blkcfg.wce) {\n+        return;\n+    }\n+\n+    ret = vhost_dev_set_config(&s->dev, config,\n+                              sizeof(struct virtio_blk_config));\n+    if (ret) {\n+        error_report(\"set device config space failed\");\n+        return;\n+    }\n+\n+    s->blkcfg.wce = blkcfg->wce;\n+}\n+\n+static void vhost_user_blk_handle_config_change(struct vhost_dev *dev)\n+{\n+    int ret;\n+    struct virtio_blk_config blkcfg;\n+    VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);\n+\n+    ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,\n+                               sizeof(struct virtio_blk_config));\n+    if (ret < 0) {\n+        error_report(\"get config space failed\");\n+        return;\n+    }\n+\n+    memcpy(&s->blkcfg, &blkcfg, sizeof(struct virtio_blk_config));\n+    memcpy(dev->vdev->config, &blkcfg, sizeof(struct virtio_blk_config));\n+\n+    virtio_notify_config(dev->vdev);\n+}\n+\n+const VhostDevConfigOps blk_ops = {\n+    .vhost_dev_config_notifier = vhost_user_blk_handle_config_change,\n+};\n+\n+static void vhost_user_blk_start(VirtIODevice *vdev)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));\n+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);\n+    int i, ret;\n+\n+    if (!k->set_guest_notifiers) {\n+        error_report(\"binding does not support guest notifiers\");\n+        return;\n+    }\n+\n+    ret = vhost_dev_enable_notifiers(&s->dev, vdev);\n+    if (ret < 0) {\n+        error_report(\"Error enabling host notifiers: %d\", -ret);\n+        return;\n+    }\n+\n+    ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true);\n+    if (ret < 0) {\n+        error_report(\"Error binding guest notifier: %d\", -ret);\n+        goto err_host_notifiers;\n+    }\n+\n+    s->dev.acked_features = vdev->guest_features;\n+    ret = vhost_dev_start(&s->dev, vdev);\n+    if (ret < 0) {\n+        error_report(\"Error starting vhost: %d\", -ret);\n+        goto err_guest_notifiers;\n+    }\n+\n+    /* guest_notifier_mask/pending not used yet, so just unmask\n+     * everything here. virtio-pci will do the right thing by\n+     * enabling/disabling irqfd.\n+     */\n+    for (i = 0; i < s->dev.nvqs; i++) {\n+        vhost_virtqueue_mask(&s->dev, vdev, i, false);\n+    }\n+\n+    return;\n+\n+err_guest_notifiers:\n+    k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);\n+err_host_notifiers:\n+    vhost_dev_disable_notifiers(&s->dev, vdev);\n+}\n+\n+static void vhost_user_blk_stop(VirtIODevice *vdev)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));\n+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);\n+    int ret;\n+\n+    if (!k->set_guest_notifiers) {\n+        return;\n+    }\n+\n+    vhost_dev_stop(&s->dev, vdev);\n+\n+    ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);\n+    if (ret < 0) {\n+        error_report(\"vhost guest notifier cleanup failed: %d\", ret);\n+        return;\n+    }\n+\n+    vhost_dev_disable_notifiers(&s->dev, vdev);\n+}\n+\n+static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+    bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;\n+\n+    if (!vdev->vm_running) {\n+        should_start = false;\n+    }\n+\n+    if (s->dev.started == should_start) {\n+        return;\n+    }\n+\n+    if (should_start) {\n+        vhost_user_blk_start(vdev);\n+    } else {\n+        vhost_user_blk_stop(vdev);\n+    }\n+\n+}\n+\n+static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,\n+                                            uint64_t features,\n+                                            Error **errp)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+    uint64_t get_features;\n+\n+    /* Turn on pre-defined features */\n+    features |= s->host_features;\n+\n+    get_features = vhost_get_features(&s->dev, user_feature_bits, features);\n+\n+    return get_features;\n+}\n+\n+static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)\n+{\n+\n+}\n+\n+static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)\n+{\n+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);\n+    VHostUserBlk *s = VHOST_USER_BLK(vdev);\n+    int i, ret;\n+\n+    if (!s->chardev.chr) {\n+        error_setg(errp, \"vhost-user-blk: chardev is mandatory\");\n+        return;\n+    }\n+\n+    if (!s->num_queues || s->num_queues > VIRTIO_QUEUE_MAX) {\n+        error_setg(errp, \"vhost-user-blk: invalid number of IO queues\");\n+        return;\n+    }\n+\n+    if (!s->queue_size) {\n+        error_setg(errp, \"vhost-user-blk: queue size must be non-zero\");\n+        return;\n+    }\n+\n+    virtio_init(vdev, \"virtio-blk\", VIRTIO_ID_BLOCK,\n+                sizeof(struct virtio_blk_config));\n+\n+    for (i = 0; i < s->num_queues; i++) {\n+        virtio_add_queue(vdev, s->queue_size,\n+                         vhost_user_blk_handle_output);\n+    }\n+\n+    s->dev.nvqs = s->num_queues;\n+    s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs);\n+    s->dev.vq_index = 0;\n+    s->dev.backend_features = 0;\n+\n+    ret = vhost_dev_init(&s->dev, &s->chardev, VHOST_BACKEND_TYPE_USER, 0);\n+    if (ret < 0) {\n+        error_setg(errp, \"vhost-user-blk: vhost initialization failed: %s\",\n+                   strerror(-ret));\n+        goto virtio_err;\n+    }\n+\n+    ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg,\n+                              sizeof(struct virtio_blk_config));\n+    if (ret < 0) {\n+        error_setg(errp, \"vhost-user-blk: get block config failed\");\n+        goto vhost_err;\n+    }\n+\n+    if (s->blkcfg.num_queues != s->num_queues) {\n+        s->blkcfg.num_queues = s->num_queues;\n+    }\n+\n+    vhost_dev_set_config_notifier(&s->dev, &blk_ops);\n+\n+    return;\n+\n+vhost_err:\n+    vhost_dev_cleanup(&s->dev);\n+virtio_err:\n+    g_free(s->dev.vqs);\n+    virtio_cleanup(vdev);\n+}\n+\n+static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)\n+{\n+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);\n+    VHostUserBlk *s = VHOST_USER_BLK(dev);\n+\n+    vhost_user_blk_set_status(vdev, 0);\n+    vhost_dev_cleanup(&s->dev);\n+    g_free(s->dev.vqs);\n+    virtio_cleanup(vdev);\n+}\n+\n+static void vhost_user_blk_instance_init(Object *obj)\n+{\n+    VHostUserBlk *s = VHOST_USER_BLK(obj);\n+\n+    device_add_bootindex_property(obj, &s->bootindex, \"bootindex\",\n+                                  \"/disk@0,0\", DEVICE(obj), NULL);\n+}\n+\n+static const VMStateDescription vmstate_vhost_user_blk = {\n+    .name = \"vhost-user-blk\",\n+    .minimum_version_id = 1,\n+    .version_id = 1,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_VIRTIO_DEVICE,\n+        VMSTATE_END_OF_LIST()\n+    },\n+};\n+\n+static Property vhost_user_blk_properties[] = {\n+    DEFINE_PROP_CHR(\"chardev\", VHostUserBlk, chardev),\n+    DEFINE_PROP_UINT16(\"num_queues\", VHostUserBlk, num_queues, 1),\n+    DEFINE_PROP_UINT32(\"queue_size\", VHostUserBlk, queue_size, 128),\n+    DEFINE_PROP_BIT64(\"f_size_max\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_SIZE_MAX, true),\n+    DEFINE_PROP_BIT64(\"f_sizemax\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_SIZE_MAX, true),\n+    DEFINE_PROP_BIT64(\"f_segmax\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_SEG_MAX, true),\n+    DEFINE_PROP_BIT64(\"f_geometry\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_GEOMETRY, true),\n+    DEFINE_PROP_BIT64(\"f_readonly\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_RO, false),\n+    DEFINE_PROP_BIT64(\"f_blocksize\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_BLK_SIZE, true),\n+    DEFINE_PROP_BIT64(\"f_topology\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_TOPOLOGY, true),\n+    DEFINE_PROP_BIT64(\"f_multiqueue\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_MQ, true),\n+    DEFINE_PROP_BIT64(\"f_flush\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_FLUSH, true),\n+    DEFINE_PROP_BIT64(\"f_barrier\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_BARRIER, false),\n+    DEFINE_PROP_BIT64(\"f_scsi\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_SCSI, false),\n+    DEFINE_PROP_BIT64(\"f_wce\", VHostUserBlk, host_features,\n+                      VIRTIO_BLK_F_WCE, false),\n+    DEFINE_PROP_END_OF_LIST(),\n+};\n+\n+static void vhost_user_blk_class_init(ObjectClass *klass, void *data)\n+{\n+    DeviceClass *dc = DEVICE_CLASS(klass);\n+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);\n+\n+    dc->props = vhost_user_blk_properties;\n+    dc->vmsd = &vmstate_vhost_user_blk;\n+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);\n+    vdc->realize = vhost_user_blk_device_realize;\n+    vdc->unrealize = vhost_user_blk_device_unrealize;\n+    vdc->get_config = vhost_user_blk_update_config;\n+    vdc->set_config = vhost_user_blk_set_config;\n+    vdc->get_features = vhost_user_blk_get_features;\n+    vdc->set_status = vhost_user_blk_set_status;\n+}\n+\n+static const TypeInfo vhost_user_blk_info = {\n+    .name = TYPE_VHOST_USER_BLK,\n+    .parent = TYPE_VIRTIO_DEVICE,\n+    .instance_size = sizeof(VHostUserBlk),\n+    .instance_init = vhost_user_blk_instance_init,\n+    .class_init = vhost_user_blk_class_init,\n+};\n+\n+static void virtio_register_types(void)\n+{\n+    type_register_static(&vhost_user_blk_info);\n+}\n+\n+type_init(virtio_register_types)\ndiff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c\nindex 8b0d6b6..be9a992 100644\n--- a/hw/virtio/virtio-pci.c\n+++ b/hw/virtio/virtio-pci.c\n@@ -2012,6 +2012,58 @@ static const TypeInfo virtio_blk_pci_info = {\n     .class_init    = virtio_blk_pci_class_init,\n };\n \n+#ifdef CONFIG_VHOST_USER_BLK\n+/* vhost-user-blk */\n+\n+static Property vhost_user_blk_pci_properties[] = {\n+    DEFINE_PROP_UINT32(\"class\", VirtIOPCIProxy, class_code, 0),\n+    DEFINE_PROP_UINT32(\"vectors\", VirtIOPCIProxy, nvectors, 2),\n+    DEFINE_PROP_END_OF_LIST(),\n+};\n+\n+static void vhost_user_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)\n+{\n+    VHostUserBlkPCI *dev = VHOST_USER_BLK_PCI(vpci_dev);\n+    DeviceState *vdev = DEVICE(&dev->vdev);\n+\n+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));\n+    object_property_set_bool(OBJECT(vdev), true, \"realized\", errp);\n+}\n+\n+static void vhost_user_blk_pci_class_init(ObjectClass *klass, void *data)\n+{\n+    DeviceClass *dc = DEVICE_CLASS(klass);\n+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);\n+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);\n+\n+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);\n+    dc->props = vhost_user_blk_pci_properties;\n+    k->realize = vhost_user_blk_pci_realize;\n+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;\n+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;\n+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;\n+    pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;\n+}\n+\n+static void vhost_user_blk_pci_instance_init(Object *obj)\n+{\n+    VHostUserBlkPCI *dev = VHOST_USER_BLK_PCI(obj);\n+\n+    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),\n+                                TYPE_VHOST_USER_BLK);\n+    object_property_add_alias(obj, \"bootindex\", OBJECT(&dev->vdev),\n+                              \"bootindex\", &error_abort);\n+}\n+\n+static const TypeInfo vhost_user_blk_pci_info = {\n+    .name           = TYPE_VHOST_USER_BLK_PCI,\n+    .parent         = TYPE_VIRTIO_PCI,\n+    .instance_size  = sizeof(VHostUserBlkPCI),\n+    .instance_init  = vhost_user_blk_pci_instance_init,\n+    .class_init     = vhost_user_blk_pci_class_init,\n+};\n+#endif\n+\n /* virtio-scsi-pci */\n \n static Property virtio_scsi_pci_properties[] = {\n@@ -2658,6 +2710,9 @@ static void virtio_pci_register_types(void)\n     type_register_static(&virtio_9p_pci_info);\n #endif\n     type_register_static(&virtio_blk_pci_info);\n+#ifdef CONFIG_VHOST_USER_BLK\n+    type_register_static(&vhost_user_blk_pci_info);\n+#endif\n     type_register_static(&virtio_scsi_pci_info);\n     type_register_static(&virtio_balloon_pci_info);\n     type_register_static(&virtio_serial_pci_info);\ndiff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h\nindex 69f5959..19a0d01 100644\n--- a/hw/virtio/virtio-pci.h\n+++ b/hw/virtio/virtio-pci.h\n@@ -27,6 +27,9 @@\n #include \"hw/virtio/virtio-gpu.h\"\n #include \"hw/virtio/virtio-crypto.h\"\n #include \"hw/virtio/vhost-user-scsi.h\"\n+#ifdef CONFIG_VHOST_USER_BLK\n+#include \"hw/virtio/vhost-user-blk.h\"\n+#endif\n \n #ifdef CONFIG_VIRTFS\n #include \"hw/9pfs/virtio-9p.h\"\n@@ -46,6 +49,7 @@ typedef struct VirtIOSerialPCI VirtIOSerialPCI;\n typedef struct VirtIONetPCI VirtIONetPCI;\n typedef struct VHostSCSIPCI VHostSCSIPCI;\n typedef struct VHostUserSCSIPCI VHostUserSCSIPCI;\n+typedef struct VHostUserBlkPCI VHostUserBlkPCI;\n typedef struct VirtIORngPCI VirtIORngPCI;\n typedef struct VirtIOInputPCI VirtIOInputPCI;\n typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;\n@@ -241,6 +245,20 @@ struct VHostUserSCSIPCI {\n     VHostUserSCSI vdev;\n };\n \n+#ifdef CONFIG_VHOST_USER_BLK\n+/*\n+ * vhost-user-blk-pci: This extends VirtioPCIProxy.\n+ */\n+#define TYPE_VHOST_USER_BLK_PCI \"vhost-user-blk-pci\"\n+#define VHOST_USER_BLK_PCI(obj) \\\n+        OBJECT_CHECK(VHostUserBlkPCI, (obj), TYPE_VHOST_USER_BLK_PCI)\n+\n+struct VHostUserBlkPCI {\n+    VirtIOPCIProxy parent_obj;\n+    VHostUserBlk vdev;\n+};\n+#endif\n+\n /*\n  * virtio-blk-pci: This extends VirtioPCIProxy.\n  */\ndiff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h\nnew file mode 100644\nindex 0000000..77d20f0\n--- /dev/null\n+++ b/include/hw/virtio/vhost-user-blk.h\n@@ -0,0 +1,40 @@\n+/*\n+ * vhost-user-blk host device\n+ * Copyright IBM, Corp. 2011\n+ * Copyright(C) 2017 Intel Corporation.\n+ *\n+ * Authors:\n+ *  Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>\n+ *  Changpeng Liu <changpeng.liu@intel.com>\n+ *\n+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.\n+ * See the COPYING.LIB file in the top-level directory.\n+ *\n+ */\n+\n+#ifndef VHOST_USER_BLK_H\n+#define VHOST_USER_BLK_H\n+\n+#include \"standard-headers/linux/virtio_blk.h\"\n+#include \"qemu-common.h\"\n+#include \"hw/qdev.h\"\n+#include \"hw/block/block.h\"\n+#include \"chardev/char-fe.h\"\n+#include \"hw/virtio/vhost.h\"\n+\n+#define TYPE_VHOST_USER_BLK \"vhost-user-blk\"\n+#define VHOST_USER_BLK(obj) \\\n+        OBJECT_CHECK(VHostUserBlk, (obj), TYPE_VHOST_USER_BLK)\n+\n+typedef struct VHostUserBlk {\n+    VirtIODevice parent_obj;\n+    CharBackend chardev;\n+    int32_t bootindex;\n+    uint64_t host_features;\n+    struct virtio_blk_config blkcfg;\n+    uint16_t num_queues;\n+    uint32_t queue_size;\n+    struct vhost_dev dev;\n+} VHostUserBlk;\n+\n+#endif\n",
    "prefixes": [
        "v3",
        "2/4"
    ]
}