Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/812236/?format=api
{ "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" ] }