From patchwork Thu Apr 19 02:39:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhiyong Wu X-Patchwork-Id: 153643 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D57F6B6F9A for ; Thu, 19 Apr 2012 13:45:10 +1000 (EST) Received: from localhost ([::1]:48307 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKhJ8-00054j-2Y for incoming@patchwork.ozlabs.org; Wed, 18 Apr 2012 22:41:18 -0400 Received: from eggs.gnu.org ([208.118.235.92]:58464) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKhIz-0004x7-Cv for qemu-devel@nongnu.org; Wed, 18 Apr 2012 22:41:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SKhIx-0002Rl-2h for qemu-devel@nongnu.org; Wed, 18 Apr 2012 22:41:08 -0400 Received: from e4.ny.us.ibm.com ([32.97.182.144]:39884) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKhIw-0002RZ-TA for qemu-devel@nongnu.org; Wed, 18 Apr 2012 22:41:06 -0400 Received: from /spool/local by e4.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 18 Apr 2012 22:41:03 -0400 Received: from d01dlp02.pok.ibm.com (9.56.224.85) by e4.ny.us.ibm.com (192.168.1.104) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 18 Apr 2012 22:40:14 -0400 Received: from d01relay05.pok.ibm.com (d01relay05.pok.ibm.com [9.56.227.237]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 8F0926E8059 for ; Wed, 18 Apr 2012 22:40:13 -0400 (EDT) Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay05.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q3J2eDc6259104 for ; Wed, 18 Apr 2012 22:40:13 -0400 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q3J2eC6t016235 for ; Wed, 18 Apr 2012 22:40:13 -0400 Received: from us.ibm.com (f15.cn.ibm.com [9.115.118.120] (may be forged)) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id q3J2e7Fx015846; Wed, 18 Apr 2012 22:40:09 -0400 Received: by us.ibm.com (sSMTP sendmail emulation); Thu, 19 Apr 2012 10:40:06 +0800 From: zwu.kernel@gmail.com To: qemu-devel@nongnu.org Date: Thu, 19 Apr 2012 10:39:04 +0800 Message-Id: <1334803149-27379-12-git-send-email-zwu.kernel@gmail.com> X-Mailer: git-send-email 1.7.6 In-Reply-To: <1334803149-27379-1-git-send-email-zwu.kernel@gmail.com> References: <1334803149-27379-1-git-send-email-zwu.kernel@gmail.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12041902-3534-0000-0000-00000798EFCA X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 32.97.182.144 Cc: stefanha@linux.vnet.ibm.com, linuxram@us.ibm.com, nab@linux-iscsi.org, zwu.kernel@gmail.com, Zhi Yong Wu , luowenj@cn.ibm.com, pbonzini@redhat.com Subject: [Qemu-devel] [PATCH 11/16] vhost-scsi: add -vhost-scsi host device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Stefan Hajnoczi This patch adds a new type of host device that drives the vhost_scsi device. The syntax to add vhost-scsi is: qemu -vhost-scsi id=vhost-scsi0,wwpn=...,tpgt=123 The virtio-scsi emulated device will make use of vhost-scsi to process virtio-scsi requests inside the kernel and hand them to the in-kernel SCSI target stack. Signed-off-by: Stefan Hajnoczi Signed-off-by: Zhi Yong Wu --- Makefile.target | 2 +- hw/qdev-properties.c | 32 ++++++++++++ hw/qdev.h | 3 + hw/vhost-scsi.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vhost-scsi.h | 28 +++++++++++ qemu-common.h | 1 + qemu-config.c | 16 ++++++ qemu-options.hx | 4 ++ vl.c | 18 +++++++ 9 files changed, 234 insertions(+), 1 deletions(-) create mode 100644 hw/vhost-scsi.c create mode 100644 hw/vhost-scsi.h diff --git a/Makefile.target b/Makefile.target index 84951a0..d748f94 100644 --- a/Makefile.target +++ b/Makefile.target @@ -219,7 +219,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o obj-$(CONFIG_NO_PCI) += pci-stub.o obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o obj-$(CONFIG_VIRTIO) += virtio-scsi.o -obj-y += vhost_net.o +obj-y += vhost_net.o vhost-scsi.o obj-$(CONFIG_VHOST_NET) += vhost.o obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 98dd06a..2a108a0 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -2,6 +2,7 @@ #include "qdev.h" #include "qerror.h" #include "blockdev.h" +#include "vhost-scsi.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { @@ -688,6 +689,37 @@ PropertyInfo qdev_prop_vlan = { .set = set_vlan, }; +/* --- vhost-scsi --- */ + +static int parse_vhost_scsi(DeviceState *dev, Property *prop, const char *str) +{ + VHostSCSI **ptr = qdev_get_prop_ptr(dev, prop); + + *ptr = find_vhost_scsi(str); + if (*ptr == NULL) { + return -ENOENT; + } + return 0; +} + +static int print_vhost_scsi(DeviceState *dev, Property *prop, + char *dest, size_t len) +{ + VHostSCSI **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + return snprintf(dest, len, "%s", vhost_scsi_get_id(*ptr)); + } else { + return snprintf(dest, len, ""); + } +} + +PropertyInfo qdev_prop_vhost_scsi = { + .name = "vhost-scsi", + .parse = parse_vhost_scsi, + .print = print_vhost_scsi, +}; + /* --- pointer --- */ /* Not a proper property, just for dirty hacks. TODO Remove it! */ diff --git a/hw/qdev.h b/hw/qdev.h index 4e90119..dc51678 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -225,6 +225,7 @@ extern PropertyInfo qdev_prop_netdev; extern PropertyInfo qdev_prop_vlan; extern PropertyInfo qdev_prop_pci_devfn; extern PropertyInfo qdev_prop_blocksize; +extern PropertyInfo qdev_prop_vhost_scsi; #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ .name = (_name), \ @@ -288,6 +289,8 @@ extern PropertyInfo qdev_prop_blocksize; LostTickPolicy) #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t) +#define DEFINE_PROP_VHOST_SCSI(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_vhost_scsi, VHostSCSI*) #define DEFINE_PROP_END_OF_LIST() \ {} diff --git a/hw/vhost-scsi.c b/hw/vhost-scsi.c new file mode 100644 index 0000000..6e3645f --- /dev/null +++ b/hw/vhost-scsi.c @@ -0,0 +1,131 @@ +/* + * vhost_scsi host device + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "config.h" +#include "qemu-queue.h" +#include "vhost-scsi.h" +#include "vhost.h" + +struct VHostSCSI { + const char *id; + const char *wwpn; + uint16_t tpgt; + struct vhost_dev dev; + struct vhost_virtqueue vqs[3]; + QLIST_ENTRY(VHostSCSI) list; +}; + +static QLIST_HEAD(, VHostSCSI) vhost_scsi_list = + QLIST_HEAD_INITIALIZER(vhost_scsi_list); + +VHostSCSI *find_vhost_scsi(const char *id) +{ + VHostSCSI *vs; + + QLIST_FOREACH(vs, &vhost_scsi_list, list) { + if (strcmp(id, vs->id) == 0) { + return vs; + } + } + return NULL; +} + +const char *vhost_scsi_get_id(VHostSCSI *vs) +{ + return vs->id; +} + +int vhost_scsi_start(VHostSCSI *vs, VirtIODevice *vdev) +{ + int ret; + + if (!vhost_dev_query(&vs->dev, vdev)) { + return -ENOTSUP; + } + + vs->dev.nvqs = 3; + vs->dev.vqs = vs->vqs; + ret = vhost_dev_start(&vs->dev, vdev); + if (ret < 0) { + return ret; + } + + /* TODO set wwpn and tpgt */ + fprintf(stderr, "vhost_scsi_start\n"); + return 0; +} + +void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev) +{ + fprintf(stderr, "vhost_scsi_stop\n"); + /* TODO clear wwpn and tpgt */ + + vhost_dev_stop(&vs->dev, vdev); +} + +static VHostSCSI *vhost_scsi_add(const char *id, const char *wwpn, + uint16_t tpgt) +{ + VHostSCSI *vs = g_malloc0(sizeof(*vs)); + int ret; + + /* TODO set up vhost-scsi device and bind to tcm_vhost/$wwpm/tpgt_$tpgt */ + fprintf(stderr, "wwpn = \"%s\" tpgt = \"%u\"\n", id, tpgt); + + ret = vhost_dev_init(&vs->dev, -1, "/dev/vhost-scsi", false); + if (ret < 0) { + fprintf(stderr, "vhost-scsi: vhost initialization failed: %s\n", + strerror(-ret)); + return NULL; + } + vs->dev.backend_features = 0; + vs->dev.acked_features = 0; + + vs->id = g_strdup(id); + vs->wwpn = g_strdup(wwpn); + vs->tpgt = tpgt; + QLIST_INSERT_HEAD(&vhost_scsi_list, vs, list); + + return vs; +} + +VHostSCSI *vhost_scsi_add_opts(QemuOpts *opts) +{ + const char *id; + const char *wwpn; + uint64_t tpgt; + + id = qemu_opts_id(opts); + if (!id) { + fprintf(stderr, "vhost-scsi: no id specified\n"); + return NULL; + } + if (find_vhost_scsi(id)) { + fprintf(stderr, "duplicate vhost-scsi: \"%s\"\n", id); + return NULL; + } + + wwpn = qemu_opt_get(opts, "wwpn"); + if (!wwpn) { + fprintf(stderr, "vhost-scsi: \"%s\" missing wwpn\n", id); + return NULL; + } + + tpgt = qemu_opt_get_number(opts, "tpgt", UINT64_MAX); + if (tpgt > UINT16_MAX) { + fprintf(stderr, "vhost-scsi: \"%s\" needs a 16-bit tpgt\n", id); + return NULL; + } + + return vhost_scsi_add(id, wwpn, tpgt); +} diff --git a/hw/vhost-scsi.h b/hw/vhost-scsi.h new file mode 100644 index 0000000..e5e67e3 --- /dev/null +++ b/hw/vhost-scsi.h @@ -0,0 +1,28 @@ +/* + * vhost_scsi host device + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef VHOST_SCSI_H +#define VHOST_SCSI_H + +#include "qemu-common.h" +#include "qemu-option.h" + +VHostSCSI *find_vhost_scsi(const char *id); +const char *vhost_scsi_get_id(VHostSCSI *vs); + +VHostSCSI *vhost_scsi_add_opts(QemuOpts *opts); + +int vhost_scsi_start(VHostSCSI *vs, VirtIODevice *vdev); +void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev); + +#endif diff --git a/qemu-common.h b/qemu-common.h index 50f659a..3bf4895 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -259,6 +259,7 @@ typedef struct EventNotifier EventNotifier; typedef struct VirtIODevice VirtIODevice; typedef struct QEMUSGList QEMUSGList; typedef struct SHPCDevice SHPCDevice; +typedef struct VHostSCSI VHostSCSI; typedef uint64_t pcibus_t; diff --git a/qemu-config.c b/qemu-config.c index be84a03..fffcbcc 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -613,6 +613,21 @@ QemuOptsList qemu_boot_opts = { }, }; +QemuOptsList qemu_vhost_scsi_opts = { + .name = "vhost-scsi", + .head = QTAILQ_HEAD_INITIALIZER(qemu_vhost_scsi_opts.head), + .desc = { + { + .name = "wwpn", + .type = QEMU_OPT_STRING, + }, { + .name = "tpgt", + .type = QEMU_OPT_NUMBER, + }, + { /* end of list */ } + }, +}; + static QemuOptsList *vm_config_groups[32] = { &qemu_drive_opts, &qemu_chardev_opts, @@ -628,6 +643,7 @@ static QemuOptsList *vm_config_groups[32] = { &qemu_machine_opts, &qemu_boot_opts, &qemu_iscsi_opts, + &qemu_vhost_scsi_opts, NULL, }; diff --git a/qemu-options.hx b/qemu-options.hx index a169792..1a580d8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -561,6 +561,10 @@ possible drivers and properties, use @code{-device ?} and ETEXI DEFHEADING() +DEF("vhost-scsi", HAS_ARG, QEMU_OPTION_vhost_scsi, + "-virtio-scsi wwpn=string0,tpgt=number0\n" + " add vhost-scsi device\n", + QEMU_ARCH_ALL) DEFHEADING(File system options:) diff --git a/vl.c b/vl.c index ae91a8a..221a294 100644 --- a/vl.c +++ b/vl.c @@ -149,6 +149,7 @@ int main(int argc, char **argv) #include "qemu-options.h" #include "qmp-commands.h" #include "main-loop.h" +#include "hw/vhost-scsi.h" #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif @@ -1850,6 +1851,14 @@ static int fsdev_init_func(QemuOpts *opts, void *opaque) } #endif +static int vhost_scsi_init_func(QemuOpts *opts, void *opaque) +{ + if (!vhost_scsi_add_opts(opts)) { + return -1; + } + return 0; +} + static int mon_init_func(QemuOpts *opts, void *opaque) { CharDriverState *chr; @@ -2611,6 +2620,11 @@ int main(int argc, char **argv, char **envp) } break; #endif + case QEMU_OPTION_vhost_scsi: + if (!qemu_opts_parse(qemu_find_opts("vhost-scsi"), optarg, 0)) { + exit(1); + } + break; #ifdef CONFIG_SLIRP case QEMU_OPTION_tftp: legacy_tftp_prefix = optarg; @@ -3322,6 +3336,10 @@ int main(int argc, char **argv, char **envp) exit(1); } #endif + if (qemu_opts_foreach(qemu_find_opts("vhost-scsi"), + vhost_scsi_init_func, NULL, 1)) { + exit(1); + } os_daemonize();