Nicholas A. Bellinger
2012-Jul-24 22:33 UTC
[RFC 0/9] vhost-scsi: Add support for host virtualized target
From: Nicholas Bellinger <nab at linux-iscsi.org> Hi Anthony + QEMU storage folks, The following is a reviewable RFC series of vhost-scsi against yesterday's QEMU.git/master @ commit 401a66357d. The series is available directly from: git://git.kernel.org/pub/scm/virt/kvm/nab/qemu-kvm.git vhost-scsi-merge It contains the squashed + re-ordered patches from Stefan -> Zhi's QEMU original work into a updated series against recent QEMU code. As mentioned recently on qemu-devel here: http://lists.gnu.org/archive/html/qemu-devel/2012-07/msg03280.html the 'vhost-scsi-merge' branch is currently failing with vhost/virtio errors using the latest HEAD. Stefan + myself are currently working through the 1.1.0 regressions, and will be posting incremental patches against this working tree as individual progress is made.. Please have a look. --nab P.S: Also, for folks who are interested in trying out a working virtio-scsi <-> tcm_vhost setup, check out using branch 'vhost-scsi' with the last pre-regression commit from upstream QEMU that appears to be performing very well. This along with target-pending.git/for-next-merge for KVM host + a virtio-scsi SCSI LLD bugfix for KVM guest that's headed into 3.6-rc1 here should be enough to get up and running: virtio-scsi: Add vdrv->scan for post VIRTIO_CONFIG_S_DRIVER_OK LUN scanning http://git.kernel.org/?p=linux/kernel/git/jejb/scsi.git;a=commitdiff;h=59057fbc37178f10a196ab7ec170b80273f75a47;hp=0b1017aab197271a78169fde3d7e487bb721997c Thanks! Nicholas Bellinger (1): virtio-scsi: Set max_target=0 during vhost-scsi operation Stefan Hajnoczi (8): notifier: add validity check and notify function virtio-pci: support host notifiers in TCG mode virtio-pci: check that event notification worked vhost: Pass device path to vhost_dev_init() virtio-scsi: Add wwpn and tgpt properties virtio-scsi: Open and initialize /dev/vhost-scsi virtio-scsi: Start/stop vhost vhost-scsi: add -vhost-scsi host device configure | 10 +++ event_notifier.c | 21 ++++++ event_notifier.h | 4 + hw/Makefile.objs | 1 + hw/qdev-properties.c | 32 +++++++++ hw/qdev.h | 3 + hw/vhost-scsi.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vhost-scsi.h | 50 ++++++++++++++ hw/vhost.c | 5 +- hw/vhost.h | 3 +- hw/vhost_net.c | 2 +- hw/virtio-pci.c | 28 +++++++- hw/virtio-scsi.c | 59 +++++++++++++++++- hw/virtio-scsi.h | 1 + hw/virtio.c | 7 ++ qemu-common.h | 1 + qemu-config.c | 16 +++++ qemu-options.hx | 4 + vl.c | 18 +++++ 19 files changed, 430 insertions(+), 8 deletions(-) create mode 100644 hw/vhost-scsi.c create mode 100644 hw/vhost-scsi.h -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:33 UTC
[RFC 1/9] notifier: add validity check and notify function
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Event notifiers that have not had the event_notifier_init() function called on them are invalid. The event_notifier_valid() function checks whether or not an event notifier is valild. This can be used to check whether a notifier is in use or not. It sometimes useful to notify the event notifier, for example when vhost is on the receiving end of the event notifier and qemu needs to notify it. The event_notifier_notify() function will signal the eventfd and increment it by one. Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Cc: Anthony Liguori <aliguori at us.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- event_notifier.c | 21 +++++++++++++++++++++ event_notifier.h | 4 ++++ 2 files changed, 25 insertions(+), 0 deletions(-) diff --git a/event_notifier.c b/event_notifier.c index 2c207e1..efe00ea 100644 --- a/event_notifier.c +++ b/event_notifier.c @@ -25,6 +25,7 @@ void event_notifier_init_fd(EventNotifier *e, int fd) int event_notifier_init(EventNotifier *e, int active) { + assert(!event_notifier_valid(e)); #ifdef CONFIG_EVENTFD int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC); if (fd < 0) @@ -39,6 +40,12 @@ int event_notifier_init(EventNotifier *e, int active) void event_notifier_cleanup(EventNotifier *e) { close(e->fd); + e->fd = -1; +} + +bool event_notifier_valid(EventNotifier *e) +{ + return e->fd != -1; } int event_notifier_get_fd(EventNotifier *e) @@ -65,3 +72,17 @@ int event_notifier_test_and_clear(EventNotifier *e) int r = read(e->fd, &value, sizeof(value)); return r == sizeof(value); } + +int event_notifier_notify(EventNotifier *e) +{ + uint64_t value = 1; + int r; + + assert(event_notifier_valid(e)); + r = write(e->fd, &value, sizeof(value)); + if (r < 0) { + return -errno; + } + assert(r == sizeof(value)); + return 0; +} diff --git a/event_notifier.h b/event_notifier.h index f0ec2f2..eea10a9 100644 --- a/event_notifier.h +++ b/event_notifier.h @@ -15,6 +15,8 @@ #include "qemu-common.h" +#define EVENT_NOTIFIER_INITIALIZER ((EventNotifier){ .fd = -1 }) + struct EventNotifier { int fd; }; @@ -24,9 +26,11 @@ typedef void EventNotifierHandler(EventNotifier *); void event_notifier_init_fd(EventNotifier *, int fd); int event_notifier_init(EventNotifier *, int active); void event_notifier_cleanup(EventNotifier *); +bool event_notifier_valid(EventNotifier *e); int event_notifier_get_fd(EventNotifier *); int event_notifier_set(EventNotifier *); int event_notifier_test_and_clear(EventNotifier *); int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *); +int event_notifier_notify(EventNotifier *e); #endif -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:33 UTC
[RFC 2/9] virtio-pci: support host notifiers in TCG mode
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Normally host notifiers are only used together with vhost-net in KVM mode. It is occassionally useful to use vhost with TCG mode, mainly for testing and development. This isn't hard to achieve, simply fall back to notifying the host notifier manually from qemu if KVM mode is disabled. Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Cc: Anthony Liguori <aliguori at us.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/virtio-pci.c | 23 ++++++++++++++++++++--- hw/virtio.c | 7 +++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 4e03f0b..538eef4 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -249,6 +249,25 @@ void virtio_pci_reset(DeviceState *d) proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG; } +static void virtio_pci_queue_notify(VirtIOPCIProxy *proxy, uint32_t n) +{ + VirtQueue *vq; + EventNotifier *notifier; + + if (n >= VIRTIO_PCI_QUEUE_MAX) { + return; + } + + vq = virtio_get_queue(proxy->vdev, n); + notifier = virtio_queue_get_host_notifier(vq); + if (event_notifier_valid(notifier)) { + printf("notifying vq %u host notifier from userspace\n", n); + event_notifier_notify(notifier); + } else { + virtio_queue_notify_vq(vq); + } +} + static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) { VirtIOPCIProxy *proxy = opaque; @@ -278,9 +297,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) vdev->queue_sel = val; break; case VIRTIO_PCI_QUEUE_NOTIFY: - if (val < VIRTIO_PCI_QUEUE_MAX) { - virtio_queue_notify(vdev, val); - } + virtio_pci_queue_notify(proxy, val); break; case VIRTIO_PCI_STATUS: if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) { diff --git a/hw/virtio.c b/hw/virtio.c index d146f86..36a18b5 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -536,6 +536,11 @@ void virtio_reset(void *opaque) vdev->vq[i].signalled_used = 0; vdev->vq[i].signalled_used_valid = false; vdev->vq[i].notification = true; + + assert(!event_notifier_valid(&vdev->vq[i].guest_notifier)); + assert(!event_notifier_valid(&vdev->vq[i].host_notifier)); + vdev->vq[i].guest_notifier = EVENT_NOTIFIER_INITIALIZER; + vdev->vq[i].host_notifier = EVENT_NOTIFIER_INITIALIZER; } } @@ -905,6 +910,8 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) { vdev->vq[i].vector = VIRTIO_NO_VECTOR; vdev->vq[i].vdev = vdev; + vdev->vq[i].guest_notifier = EVENT_NOTIFIER_INITIALIZER; + vdev->vq[i].host_notifier = EVENT_NOTIFIER_INITIALIZER; } vdev->name = name; -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:34 UTC
[RFC 3/9] virtio-pci: check that event notification worked
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> For sanity assert that event notification succeeds. Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Cc: Anthony Liguori <aliguori at us.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/virtio-pci.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 538eef4..0f0f766 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -261,8 +261,11 @@ static void virtio_pci_queue_notify(VirtIOPCIProxy *proxy, uint32_t n) vq = virtio_get_queue(proxy->vdev, n); notifier = virtio_queue_get_host_notifier(vq); if (event_notifier_valid(notifier)) { + int r; + printf("notifying vq %u host notifier from userspace\n", n); - event_notifier_notify(notifier); + r = event_notifier_notify(notifier); + assert(r == 0); } else { virtio_queue_notify_vq(vq); } -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:34 UTC
[RFC 4/9] vhost: Pass device path to vhost_dev_init()
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> The path to /dev/vhost-net is currently hardcoded in vhost_dev_init(). This needs to be changed so that /dev/vhost-scsi can be used. Pass in the device path instead of hardcoding it. Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Cc: Michael S. Tsirkin <mst at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/vhost.c | 5 +++-- hw/vhost.h | 3 ++- hw/vhost_net.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/vhost.c b/hw/vhost.c index 0fd8da8..d0ce5aa 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -747,14 +747,15 @@ static void vhost_eventfd_del(MemoryListener *listener, { } -int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force) +int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, + bool force) { uint64_t features; int r; if (devfd >= 0) { hdev->control = devfd; } else { - hdev->control = open("/dev/vhost-net", O_RDWR); + hdev->control = open(devpath, O_RDWR); if (hdev->control < 0) { return -errno; } diff --git a/hw/vhost.h b/hw/vhost.h index 80e64df..0c47229 100644 --- a/hw/vhost.h +++ b/hw/vhost.h @@ -44,7 +44,8 @@ struct vhost_dev { bool force; }; -int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force); +int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, + bool force); void vhost_dev_cleanup(struct vhost_dev *hdev); bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); diff --git a/hw/vhost_net.c b/hw/vhost_net.c index 75f8211..9faadfd 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -109,7 +109,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd, (1 << VHOST_NET_F_VIRTIO_NET_HDR); net->backend = r; - r = vhost_dev_init(&net->dev, devfd, force); + r = vhost_dev_init(&net->dev, devfd, "/dev/vhost-net", force); if (r < 0) { goto fail; } -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:34 UTC
[RFC 5/9] virtio-scsi: Add wwpn and tgpt properties
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> A vhost-scsi device must be bound to a tcm_vhost target port. This will be done by issuing an ioctl to the device with the wwpn and tgpt. This patch adds these properties to the virtio-scsi-pci device: qemu -device virtio-scsi-pci,wwpn=$TARGET_WWN,tgpt=$TPGT Future patches will open /dev/vhost-scsi and issue the ioctl. This patch also moves the virtio_scsi_init() prototype to hw/virtio-scsi.h where the VirtIOSCSIConf structure is defined. I think this is cleaner than defining it in hw/virtio.h. (v2: Use modern VirtIOSCSIConf define in virtio-scsi.h) Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Cc: Michael S. Tsirkin <mst at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/virtio-scsi.c | 2 ++ hw/virtio-scsi.h | 1 + 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 0a5ac40..4a787d3 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -13,6 +13,8 @@ * */ +#include "qemu-common.h" +#include "qemu-error.h" #include "virtio-scsi.h" #include <hw/scsi.h> #include <hw/scsi-defs.h> diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h index 4bc889d..74e9422 100644 --- a/hw/virtio-scsi.h +++ b/hw/virtio-scsi.h @@ -22,6 +22,7 @@ #define VIRTIO_ID_SCSI 8 struct VirtIOSCSIConf { + VHostSCSI *vhost_scsi; uint32_t num_queues; uint32_t max_sectors; uint32_t cmd_per_lun; -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:34 UTC
[RFC 6/9] virtio-scsi: Open and initialize /dev/vhost-scsi
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Begin adding vhost support by opening /dev/vhost-scsi. (v2: Drop legacy ->vhost_vqs[] usage) Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> Cc: Michael S. Tsirkin <mst at redhat.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/virtio-scsi.c | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 4a787d3..dea3269 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -18,6 +18,7 @@ #include "virtio-scsi.h" #include <hw/scsi.h> #include <hw/scsi-defs.h> +#include "vhost.h" #define VIRTIO_SCSI_VQ_SIZE 128 #define VIRTIO_SCSI_CDB_SIZE 32 @@ -137,6 +138,9 @@ typedef struct { VirtQueue *ctrl_vq; VirtQueue *event_vq; VirtQueue *cmd_vqs[0]; + + bool vhost_started; + VHostSCSI *vhost_scsi; } VirtIOSCSI; typedef struct VirtIOSCSIReq { @@ -456,6 +460,11 @@ static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req) virtio_scsi_complete_req(req); } +static VirtIOSCSI *to_virtio_scsi(VirtIODevice *vdev) +{ + return (VirtIOSCSI *)vdev; +} + static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) { VirtIOSCSI *s = (VirtIOSCSI *)vdev; @@ -605,6 +614,8 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) s->qdev = dev; s->conf = proxyconf; + s->vhost_started = false; + s->vhost_scsi = proxyconf->vhost_scsi; /* TODO set up vdev function pointers */ s->vdev.get_config = virtio_scsi_get_config; @@ -636,5 +647,6 @@ void virtio_scsi_exit(VirtIODevice *vdev) { VirtIOSCSI *s = (VirtIOSCSI *)vdev; unregister_savevm(s->qdev, "virtio-scsi", s); + vhost_dev_cleanup(&s->vhost_scsi); virtio_cleanup(vdev); } -- 1.7.2.5
From: Stefan Hajnoczi <stefanha at 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. (v2: Squash virtio-scsi: use the vhost-scsi host device from stefan) Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> Cc: Michael S. Tsirkin <mst at redhat.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/virtio-pci.c | 2 ++ hw/virtio-scsi.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 0f0f766..64f2f0d 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -1060,6 +1060,8 @@ static int virtio_scsi_exit_pci(PCIDevice *pci_dev) } static Property virtio_scsi_properties[] = { + DEFINE_PROP_VHOST_SCSI("vhost-scsi", VirtIOPCIProxy, + scsi.vhost_scsi), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index dea3269..b0adfde 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -15,6 +15,7 @@ #include "qemu-common.h" #include "qemu-error.h" +#include "vhost-scsi.h" #include "virtio-scsi.h" #include <hw/scsi.h> #include <hw/scsi-defs.h> @@ -601,6 +602,38 @@ 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; + + ret = vhost_scsi_start(s->vhost_scsi, vdev); + 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 { + vhost_scsi_stop(s->vhost_scsi, vdev); + } + + s->vhost_started = start; +} + VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) { VirtIOSCSI *s; @@ -622,6 +655,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); @@ -647,6 +683,9 @@ void virtio_scsi_exit(VirtIODevice *vdev) { VirtIOSCSI *s = (VirtIOSCSI *)vdev; unregister_savevm(s->qdev, "virtio-scsi", s); - vhost_dev_cleanup(&s->vhost_scsi); + + /* This will stop vhost backend if appropriate. */ + virtio_scsi_set_status(vdev, 0); + virtio_cleanup(vdev); } -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:34 UTC
[RFC 8/9] virtio-scsi: Set max_target=0 during vhost-scsi operation
From: Nicholas Bellinger <nab at linux-iscsi.org> This QEMU patch sets VirtIOSCSIConfig->max_target=0 for vhost-scsi operation to restrict virtio-scsi LLD guest scanning to max_id=0 (a single target ID instance) when connected to individual tcm_vhost endpoints. This ensures that virtio-scsi LLD only attempts to scan target IDs up to VIRTIO_SCSI_MAX_TARGET when connected via virtio-scsi-raw. Cc: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Cc: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- hw/virtio-scsi.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index b0adfde..d854998 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -534,7 +534,11 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, stl_raw(&scsiconf->sense_size, s->sense_size); stl_raw(&scsiconf->cdb_size, s->cdb_size); stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL); - stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET); + if (s->vhost_scsi) { + stl_raw(&scsiconf->max_target, 0); + } else { + stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET); + } stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN); } -- 1.7.2.5
Nicholas A. Bellinger
2012-Jul-24 22:34 UTC
[RFC 9/9] vhost-scsi: add -vhost-scsi host device
From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> 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. Changelog v0 -> v1: - Add VHOST_SCSI_SET_ENDPOINT call (stefan) - Enable vhost notifiers for multiple queues (Zhi) - clear vhost-scsi endpoint on stopped (Zhi) - Add CONFIG_VHOST_SCSI for QEMU build configure (nab) - Rename vhost_vring_target -> vhost_scsi_target (mst + nab) - Add support for VHOST_SCSI_GET_ABI_VERSION ioctl (aliguori + nab) Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> Cc: Anthony Liguori <aliguori at us.ibm.com> Cc: Paolo Bonzini <pbonzini at redhat.com> Cc: Michael S. Tsirkin <mst at redhat.com> Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> --- configure | 10 +++ hw/Makefile.objs | 1 + hw/qdev-properties.c | 32 +++++++++ hw/qdev.h | 3 + hw/vhost-scsi.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vhost-scsi.h | 50 ++++++++++++++ qemu-common.h | 1 + qemu-config.c | 16 +++++ qemu-options.hx | 4 + vl.c | 18 +++++ 10 files changed, 308 insertions(+), 0 deletions(-) create mode 100644 hw/vhost-scsi.c create mode 100644 hw/vhost-scsi.h diff --git a/configure b/configure index cef0a71..2291e7e 100755 --- a/configure +++ b/configure @@ -144,6 +144,7 @@ libattr="" xfs="" vhost_net="no" +vhost_scsi="no" kvm="no" gprof="no" debug_tcg="no" @@ -489,6 +490,7 @@ Haiku) usb="linux" kvm="yes" vhost_net="yes" + vhost_scsi="yes" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then audio_possible_drivers="$audio_possible_drivers fmod" fi @@ -794,6 +796,10 @@ for opt do ;; --enable-vhost-net) vhost_net="yes" ;; + --disable-vhost-net) vhost_scsi="no" + ;; + --enable-vhost-net) vhost_scsi="yes" + ;; --disable-opengl) opengl="no" ;; --enable-opengl) opengl="yes" @@ -3059,6 +3065,7 @@ echo "posix_madvise $posix_madvise" echo "uuid support $uuid" echo "libcap-ng support $cap_ng" echo "vhost-net support $vhost_net" +echo "vhost-scsi support $vhost_scsi" echo "Trace backend $trace_backend" echo "Trace output file $trace_file-<pid>" echo "spice support $spice" @@ -3762,6 +3769,9 @@ case "$target_arch2" in if test "$vhost_net" = "yes" ; then echo "CONFIG_VHOST_NET=y" >> $config_target_mak fi + if test "$vhost_scsi" = "yes" ; then + echo "CONFIG_VHOST_SCSI=y" >> $config_target_mak + fi fi esac case "$target_arch2" in diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 8327e55..37a0d0e 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -161,6 +161,7 @@ obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o obj-$(CONFIG_SOFTMMU) += vhost_net.o obj-$(CONFIG_VHOST_NET) += vhost.o +obj-$(CONFIG_VHOST_SCSI) += vhost-scsi.o obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/ obj-$(CONFIG_NO_PCI) += pci-stub.o obj-$(CONFIG_VGA) += vga.o diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 24b39e8..0c538d2 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -3,6 +3,7 @@ #include "qerror.h" #include "blockdev.h" #include "hw/block-common.h" +#include "vhost-scsi.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { @@ -685,6 +686,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, "<null>"); + } +} + +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 a2cbd9d..ddc0791 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -238,6 +238,7 @@ extern PropertyInfo qdev_prop_vlan; extern PropertyInfo qdev_prop_pci_devfn; extern PropertyInfo qdev_prop_blocksize; extern PropertyInfo qdev_prop_pci_host_devaddr; +extern PropertyInfo qdev_prop_vhost_scsi; #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ .name = (_name), \ @@ -305,6 +306,8 @@ extern PropertyInfo qdev_prop_pci_host_devaddr; DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t) #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) +#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..9ab314c --- /dev/null +++ b/hw/vhost-scsi.c @@ -0,0 +1,173 @@ +/* + * vhost_scsi host device + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> + * + * 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 <sys/ioctl.h> +#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; + struct vhost_scsi_target backend; + + if (!vhost_dev_query(&vs->dev, vdev)) { + return -ENOTSUP; + } + + vs->dev.nvqs = 3; + vs->dev.vqs = vs->vqs; + + ret = vhost_dev_enable_notifiers(&vs->dev, vdev); + if (ret < 0) { + return ret; + } + + ret = vhost_dev_start(&vs->dev, vdev); + if (ret < 0) { + return ret; + } + + memset(&backend, 0, sizeof(backend)); + ret = ioctl(vs->dev.control, VHOST_SCSI_GET_ABI_VERSION, &backend); + if (ret < 0) { + ret = -errno; + vhost_dev_stop(&vs->dev, vdev); + return ret; + } + if (backend.abi_version > VHOST_SCSI_ABI_VERSION) { + fprintf(stderr, "The running tcm_vhost kernel abi_version: %d is greater" + " than vhost_scsi userspace supports: %d\n", backend.abi_version, + VHOST_SCSI_ABI_VERSION); + ret = -ENOSYS; + vhost_dev_stop(&vs->dev, vdev); + return ret; + } + printf("Using TCM_Vhost ABI version: %d\n", backend.abi_version); + + pstrcpy((char *)backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->wwpn); + backend.vhost_tpgt = vs->tpgt; + ret = ioctl(vs->dev.control, VHOST_SCSI_SET_ENDPOINT, &backend); + if (ret < 0) { + ret = -errno; + vhost_dev_stop(&vs->dev, vdev); + return ret; + } + + fprintf(stderr, "vhost_scsi_start\n"); + return 0; +} + +void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev) +{ + fprintf(stderr, "vhost_scsi_stop\n"); + + int ret; + struct vhost_scsi_target backend; + + pstrcpy((char *)backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->wwpn); + backend.vhost_tpgt = vs->tpgt; + ret = ioctl(vs->dev.control, VHOST_SCSI_CLEAR_ENDPOINT, &backend); + if (ret < 0) { + fprintf(stderr, "Failed to clear endpoint\n"); + } + + 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..fb6d37a --- /dev/null +++ b/hw/vhost-scsi.h @@ -0,0 +1,50 @@ +/* + * vhost_scsi host device + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> + * + * 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" + +/* + * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. + * + * ABI Rev 0: All pre 2012 revisions used by prototype out-of-tree code + * ABI Rev 1: 2012 version for v3.6 kernel merge candidate + */ + +#define VHOST_SCSI_ABI_VERSION 1 + +/* TODO #include <linux/vhost.h> properly */ +/* For VHOST_SCSI_SET_ENDPOINT/VHOST_SCSI_CLEAR_ENDPOINT ioctl */ +struct vhost_scsi_target { + int abi_version; + unsigned char vhost_wwpn[224]; + unsigned short vhost_tpgt; +}; + +#define VHOST_VIRTIO 0xAF +#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) +#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) +#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, struct vhost_scsi_target) + +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 7c8dac8..ce431b7 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -262,6 +262,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 5c3296b..33399ea 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -626,6 +626,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, @@ -641,6 +656,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 dc68e15..c3911a8 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 8904db1..063ca1d 100644 --- a/vl.c +++ b/vl.c @@ -143,6 +143,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 @@ -1854,6 +1855,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; @@ -2613,6 +2622,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; @@ -3333,6 +3347,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(); -- 1.7.2.5
Zhi Yong Wu
2012-Jul-25 02:53 UTC
[RFC 0/9] vhost-scsi: Add support for host virtualized target
On Wed, Jul 25, 2012 at 6:33 AM, Nicholas A. Bellinger <nab at linux-iscsi.org> wrote:> From: Nicholas Bellinger <nab at linux-iscsi.org> > > Hi Anthony + QEMU storage folks, > > The following is a reviewable RFC series of vhost-scsi against yesterday's > QEMU.git/master @ commit 401a66357d. > > The series is available directly from: > > git://git.kernel.org/pub/scm/virt/kvm/nab/qemu-kvm.git vhost-scsi-mergeIs this git tree cloned from qemu-kvm.git/master or qemu.git/master? But from above info, it seems to be from latter. I got confused.> > It contains the squashed + re-ordered patches from Stefan -> Zhi's QEMU > original work into a updated series against recent QEMU code. > > As mentioned recently on qemu-devel here: > > http://lists.gnu.org/archive/html/qemu-devel/2012-07/msg03280.html > > the 'vhost-scsi-merge' branch is currently failing with vhost/virtio > errors using the latest HEAD. Stefan + myself are currently working through > the 1.1.0 regressions, and will be posting incremental patches against this > working tree as individual progress is made.. > > Please have a look. > > --nab > > P.S: > > Also, for folks who are interested in trying out a working virtio-scsi <-> tcm_vhost > setup, check out using branch 'vhost-scsi' with the last pre-regression > commit from upstream QEMU that appears to be performing very well. > > This along with target-pending.git/for-next-merge for KVM host + a virtio-scsi > SCSI LLD bugfix for KVM guest that's headed into 3.6-rc1 here should be enough > to get up and running: > > virtio-scsi: Add vdrv->scan for post VIRTIO_CONFIG_S_DRIVER_OK LUN scanning > http://git.kernel.org/?p=linux/kernel/git/jejb/scsi.git;a=commitdiff;h=59057fbc37178f10a196ab7ec170b80273f75a47;hp=0b1017aab197271a78169fde3d7e487bb721997c > > Thanks! > > Nicholas Bellinger (1): > virtio-scsi: Set max_target=0 during vhost-scsi operation > > Stefan Hajnoczi (8): > notifier: add validity check and notify function > virtio-pci: support host notifiers in TCG mode > virtio-pci: check that event notification worked > vhost: Pass device path to vhost_dev_init() > virtio-scsi: Add wwpn and tgpt properties > virtio-scsi: Open and initialize /dev/vhost-scsi > virtio-scsi: Start/stop vhost > vhost-scsi: add -vhost-scsi host device > > configure | 10 +++ > event_notifier.c | 21 ++++++ > event_notifier.h | 4 + > hw/Makefile.objs | 1 + > hw/qdev-properties.c | 32 +++++++++ > hw/qdev.h | 3 + > hw/vhost-scsi.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/vhost-scsi.h | 50 ++++++++++++++ > hw/vhost.c | 5 +- > hw/vhost.h | 3 +- > hw/vhost_net.c | 2 +- > hw/virtio-pci.c | 28 +++++++- > hw/virtio-scsi.c | 59 +++++++++++++++++- > hw/virtio-scsi.h | 1 + > hw/virtio.c | 7 ++ > qemu-common.h | 1 + > qemu-config.c | 16 +++++ > qemu-options.hx | 4 + > vl.c | 18 +++++ > 19 files changed, 430 insertions(+), 8 deletions(-) > create mode 100644 hw/vhost-scsi.c > create mode 100644 hw/vhost-scsi.h > > -- > 1.7.2.5 > > -- > You received this message because you are subscribed to the Google Groups "Linux-iSCSI.org Target Development" group. > To post to this group, send email to linux-iscsi-target-dev at googlegroups.com. > To unsubscribe from this group, send email to linux-iscsi-target-dev+unsubscribe at googlegroups.com. > For more options, visit this group at http://groups.google.com/group/linux-iscsi-target-dev?hl=en. >-- Regards, Zhi Yong Wu
Il 25/07/2012 00:34, Nicholas A. Bellinger ha scritto:> From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > > 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. > > Changelog v0 -> v1: > > - Add VHOST_SCSI_SET_ENDPOINT call (stefan) > - Enable vhost notifiers for multiple queues (Zhi) > - clear vhost-scsi endpoint on stopped (Zhi) > - Add CONFIG_VHOST_SCSI for QEMU build configure (nab) > - Rename vhost_vring_target -> vhost_scsi_target (mst + nab) > - Add support for VHOST_SCSI_GET_ABI_VERSION ioctl (aliguori + nab) > > Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> > Cc: Anthony Liguori <aliguori at us.ibm.com> > Cc: Paolo Bonzini <pbonzini at redhat.com> > Cc: Michael S. Tsirkin <mst at redhat.com> > Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> > --- > configure | 10 +++ > hw/Makefile.objs | 1 + > hw/qdev-properties.c | 32 +++++++++ > hw/qdev.h | 3 + > hw/vhost-scsi.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/vhost-scsi.h | 50 ++++++++++++++ > qemu-common.h | 1 + > qemu-config.c | 16 +++++ > qemu-options.hx | 4 + > vl.c | 18 +++++ > 10 files changed, 308 insertions(+), 0 deletions(-) > create mode 100644 hw/vhost-scsi.c > create mode 100644 hw/vhost-scsi.h > > diff --git a/configure b/configure > index cef0a71..2291e7e 100755 > --- a/configure > +++ b/configure > @@ -144,6 +144,7 @@ libattr="" > xfs="" > > vhost_net="no" > +vhost_scsi="no" > kvm="no" > gprof="no" > debug_tcg="no" > @@ -489,6 +490,7 @@ Haiku) > usb="linux" > kvm="yes" > vhost_net="yes" > + vhost_scsi="yes" > if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then > audio_possible_drivers="$audio_possible_drivers fmod" > fi > @@ -794,6 +796,10 @@ for opt do > ;; > --enable-vhost-net) vhost_net="yes" > ;; > + --disable-vhost-net) vhost_scsi="no" > + ;; > + --enable-vhost-net) vhost_scsi="yes" > + ;;Case labels are using vhost-net.> --disable-opengl) opengl="no" > ;; > --enable-opengl) opengl="yes" > @@ -3059,6 +3065,7 @@ echo "posix_madvise $posix_madvise" > echo "uuid support $uuid" > echo "libcap-ng support $cap_ng" > echo "vhost-net support $vhost_net" > +echo "vhost-scsi support $vhost_scsi" > echo "Trace backend $trace_backend" > echo "Trace output file $trace_file-<pid>" > echo "spice support $spice" > @@ -3762,6 +3769,9 @@ case "$target_arch2" in > if test "$vhost_net" = "yes" ; then > echo "CONFIG_VHOST_NET=y" >> $config_target_mak > fi > + if test "$vhost_scsi" = "yes" ; then > + echo "CONFIG_VHOST_SCSI=y" >> $config_target_mak > + fi > fi > esac > case "$target_arch2" in > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > index 8327e55..37a0d0e 100644 > --- a/hw/Makefile.objs > +++ b/hw/Makefile.objs > @@ -161,6 +161,7 @@ obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o > obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o > obj-$(CONFIG_SOFTMMU) += vhost_net.o > obj-$(CONFIG_VHOST_NET) += vhost.o > +obj-$(CONFIG_VHOST_SCSI) += vhost-scsi.o > obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/ > obj-$(CONFIG_NO_PCI) += pci-stub.o > obj-$(CONFIG_VGA) += vga.o > diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c > index 24b39e8..0c538d2 100644 > --- a/hw/qdev-properties.c > +++ b/hw/qdev-properties.c > @@ -3,6 +3,7 @@ > #include "qerror.h" > #include "blockdev.h" > #include "hw/block-common.h" > +#include "vhost-scsi.h" > > void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) > { > @@ -685,6 +686,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, "<null>"); > + } > +} > + > +PropertyInfo qdev_prop_vhost_scsi = { > + .name = "vhost-scsi", > + .parse = parse_vhost_scsi, > + .print = print_vhost_scsi, > +};This has changed, see how we do get_netdev/set_netdev.> /* --- pointer --- */ > > /* Not a proper property, just for dirty hacks. TODO Remove it! */ > diff --git a/hw/qdev.h b/hw/qdev.h > index a2cbd9d..ddc0791 100644 > --- a/hw/qdev.h > +++ b/hw/qdev.h > @@ -238,6 +238,7 @@ extern PropertyInfo qdev_prop_vlan; > extern PropertyInfo qdev_prop_pci_devfn; > extern PropertyInfo qdev_prop_blocksize; > extern PropertyInfo qdev_prop_pci_host_devaddr; > +extern PropertyInfo qdev_prop_vhost_scsi; > > #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ > .name = (_name), \ > @@ -305,6 +306,8 @@ extern PropertyInfo qdev_prop_pci_host_devaddr; > DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t) > #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ > DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) > +#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..9ab314c > --- /dev/null > +++ b/hw/vhost-scsi.c > @@ -0,0 +1,173 @@ > +/* > + * vhost_scsi host device > + * > + * Copyright IBM, Corp. 2011 > + * > + * Authors: > + * Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > + * > + * 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 <sys/ioctl.h> > +#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; > + struct vhost_scsi_target backend; > + > + if (!vhost_dev_query(&vs->dev, vdev)) { > + return -ENOTSUP; > + } > + > + vs->dev.nvqs = 3; > + vs->dev.vqs = vs->vqs; > + > + ret = vhost_dev_enable_notifiers(&vs->dev, vdev); > + if (ret < 0) { > + return ret; > + } > + > + ret = vhost_dev_start(&vs->dev, vdev); > + if (ret < 0) { > + return ret; > + } > + > + memset(&backend, 0, sizeof(backend)); > + ret = ioctl(vs->dev.control, VHOST_SCSI_GET_ABI_VERSION, &backend); > + if (ret < 0) { > + ret = -errno; > + vhost_dev_stop(&vs->dev, vdev); > + return ret; > + } > + if (backend.abi_version > VHOST_SCSI_ABI_VERSION) { > + fprintf(stderr, "The running tcm_vhost kernel abi_version: %d is greater" > + " than vhost_scsi userspace supports: %d\n", backend.abi_version, > + VHOST_SCSI_ABI_VERSION); > + ret = -ENOSYS; > + vhost_dev_stop(&vs->dev, vdev); > + return ret; > + } > + printf("Using TCM_Vhost ABI version: %d\n", backend.abi_version); > + > + pstrcpy((char *)backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->wwpn); > + backend.vhost_tpgt = vs->tpgt; > + ret = ioctl(vs->dev.control, VHOST_SCSI_SET_ENDPOINT, &backend); > + if (ret < 0) { > + ret = -errno; > + vhost_dev_stop(&vs->dev, vdev); > + return ret; > + } > + > + fprintf(stderr, "vhost_scsi_start\n"); > + return 0; > +} > + > +void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev) > +{ > + fprintf(stderr, "vhost_scsi_stop\n"); > + > + int ret; > + struct vhost_scsi_target backend; > + > + pstrcpy((char *)backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->wwpn); > + backend.vhost_tpgt = vs->tpgt; > + ret = ioctl(vs->dev.control, VHOST_SCSI_CLEAR_ENDPOINT, &backend); > + if (ret < 0) { > + fprintf(stderr, "Failed to clear endpoint\n"); > + } > + > + 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..fb6d37a > --- /dev/null > +++ b/hw/vhost-scsi.h > @@ -0,0 +1,50 @@ > +/* > + * vhost_scsi host device > + * > + * Copyright IBM, Corp. 2011 > + * > + * Authors: > + * Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > + * > + * 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" > + > +/* > + * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. > + * > + * ABI Rev 0: All pre 2012 revisions used by prototype out-of-tree code > + * ABI Rev 1: 2012 version for v3.6 kernel merge candidate > + */ > + > +#define VHOST_SCSI_ABI_VERSION 1 > + > +/* TODO #include <linux/vhost.h> properly */ > +/* For VHOST_SCSI_SET_ENDPOINT/VHOST_SCSI_CLEAR_ENDPOINT ioctl */ > +struct vhost_scsi_target { > + int abi_version; > + unsigned char vhost_wwpn[224]; > + unsigned short vhost_tpgt; > +}; > + > +#define VHOST_VIRTIO 0xAF > +#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) > +#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) > +#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, struct vhost_scsi_target) > + > +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 7c8dac8..ce431b7 100644 > --- a/qemu-common.h > +++ b/qemu-common.h > @@ -262,6 +262,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 5c3296b..33399ea 100644 > --- a/qemu-config.c > +++ b/qemu-config.c > @@ -626,6 +626,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, > + },Why have the wwpn and tpgt (which should really be tgpt) both in vhost-scsi and in virtio-scsi? Can we just add them to vhost-scsi?> + { /* end of list */ } > + }, > +}; > + > static QemuOptsList *vm_config_groups[32] = { > &qemu_drive_opts, > &qemu_chardev_opts, > @@ -641,6 +656,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 dc68e15..c3911a8 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"-vhost-scsi, not -virtio-scsi.> + " add vhost-scsi device\n", > + QEMU_ARCH_ALL) > > DEFHEADING(File system options:) > > diff --git a/vl.c b/vl.c > index 8904db1..063ca1d 100644 > --- a/vl.c > +++ b/vl.c > @@ -143,6 +143,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 > @@ -1854,6 +1855,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; > @@ -2613,6 +2622,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; > @@ -3333,6 +3347,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(); > >
Il 25/07/2012 00:34, Nicholas A. Bellinger ha scritto:> From: Stefan Hajnoczi <stefanha at 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. > > (v2: Squash virtio-scsi: use the vhost-scsi host device from stefan) > > Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> > Cc: Michael S. Tsirkin <mst at redhat.com> > Cc: Paolo Bonzini <pbonzini at redhat.com> > Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org>Hmm, this is not what the patch does... :) Paolo
Il 25/07/2012 09:01, Paolo Bonzini ha scritto:>> > From: Stefan Hajnoczi <stefanha at 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. >> > >> > (v2: Squash virtio-scsi: use the vhost-scsi host device from stefan) >> > >> > Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> >> > Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> >> > Cc: Michael S. Tsirkin <mst at redhat.com> >> > Cc: Paolo Bonzini <pbonzini at redhat.com> >> > Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> > Hmm, this is not what the patch does... :)Oops, the above comment was meant for patch 5. Which is a one-liner that can be squashed here. Anyway there is some problem with the ordering of the patches, because this patch includes vhost-scsi.h (introduced in patch 9) and patch 5 uses VHostSCSI (defined by vhost-scsi.h). Paolo
Paolo Bonzini
2012-Jul-25 07:05 UTC
[RFC 6/9] virtio-scsi: Open and initialize /dev/vhost-scsi
Il 25/07/2012 00:34, Nicholas A. Bellinger ha scritto:> From: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > > Begin adding vhost support by opening /dev/vhost-scsi. > > (v2: Drop legacy ->vhost_vqs[] usage) > > Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com> > Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com> > Cc: Michael S. Tsirkin <mst at redhat.com> > Cc: Paolo Bonzini <pbonzini at redhat.com> > Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org> > --- > hw/virtio-scsi.c | 12 ++++++++++++ > 1 files changed, 12 insertions(+), 0 deletions(-) > > diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c > index 4a787d3..dea3269 100644 > --- a/hw/virtio-scsi.c > +++ b/hw/virtio-scsi.c > @@ -18,6 +18,7 @@ > #include "virtio-scsi.h" > #include <hw/scsi.h> > #include <hw/scsi-defs.h> > +#include "vhost.h" > > #define VIRTIO_SCSI_VQ_SIZE 128 > #define VIRTIO_SCSI_CDB_SIZE 32 > @@ -137,6 +138,9 @@ typedef struct { > VirtQueue *ctrl_vq; > VirtQueue *event_vq; > VirtQueue *cmd_vqs[0]; > + > + bool vhost_started; > + VHostSCSI *vhost_scsi; > } VirtIOSCSI; > > typedef struct VirtIOSCSIReq { > @@ -456,6 +460,11 @@ static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req) > virtio_scsi_complete_req(req); > } > > +static VirtIOSCSI *to_virtio_scsi(VirtIODevice *vdev) > +{ > + return (VirtIOSCSI *)vdev; > +}This function is unused and, because it is static, it will break compilation. Not that it would compile anyway since VHostSCSI is not defined yet... ;)> static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) > { > VirtIOSCSI *s = (VirtIOSCSI *)vdev; > @@ -605,6 +614,8 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) > > s->qdev = dev; > s->conf = proxyconf; > + s->vhost_started = false; > + s->vhost_scsi = proxyconf->vhost_scsi;No need for this, just use s->conf->vhost_scsi. Also, please do not register the QEMU SCSI bus if vhost-scsi is active. Paolo> > /* TODO set up vdev function pointers */ > s->vdev.get_config = virtio_scsi_get_config; > @@ -636,5 +647,6 @@ void virtio_scsi_exit(VirtIODevice *vdev) > { > VirtIOSCSI *s = (VirtIOSCSI *)vdev; > unregister_savevm(s->qdev, "virtio-scsi", s); > + vhost_dev_cleanup(&s->vhost_scsi); > virtio_cleanup(vdev); > } >
Maybe Matching Threads
- [RFC 0/9] vhost-scsi: Add support for host virtualized target
- [RFC-v2 0/6] vhost-scsi: Add support for host virtualized target
- [RFC-v2 0/6] vhost-scsi: Add support for host virtualized target
- [RFC-v3 0/5] vhost-scsi: Add support for host virtualized target
- [RFC-v3 0/5] vhost-scsi: Add support for host virtualized target