* [PATCH V2 02/18] Drivers: hv: Add KVP definitions for IP address injection
From: K. Y. Srinivasan @ 2012-08-13 17:06 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, ben
Cc: K. Y. Srinivasan
In-Reply-To: <1344877627-21779-1-git-send-email-kys@microsoft.com>
Add the necessary definitions for supporting the IP injection functionality.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Olaf Hering <olaf@aepfle.de>
Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
---
drivers/hv/hv_util.c | 4 +-
include/linux/hyperv.h | 76 ++++++++++++++++++++++++++++++++++++++++++++-
tools/hv/hv_kvp_daemon.c | 2 +-
3 files changed, 77 insertions(+), 5 deletions(-)
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index d3ac6a4..a0667de 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -263,7 +263,7 @@ static int util_probe(struct hv_device *dev,
(struct hv_util_service *)dev_id->driver_data;
int ret;
- srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
if (!srv->recv_buffer)
return -ENOMEM;
if (srv->util_init) {
@@ -274,7 +274,7 @@ static int util_probe(struct hv_device *dev,
}
}
- ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+ ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
srv->util_cb, dev->channel);
if (ret)
goto error;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 68ed7f7..11afc4e 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -122,12 +122,53 @@
#define REG_U32 4
#define REG_U64 8
+/*
+ * As we look at expanding the KVP functionality to include
+ * IP injection functionality, we need to maintain binary
+ * compatibility with older daemons.
+ *
+ * The KVP opcodes are defined by the host and it was unfortunate
+ * that I chose to treat the registration operation as part of the
+ * KVP operations defined by the host.
+ * Here is the level of compatibility
+ * (between the user level daemon and the kernel KVP driver) that we
+ * will implement:
+ *
+ * An older daemon will always be supported on a newer driver.
+ * A given user level daemon will require a minimal version of the
+ * kernel driver.
+ * If we cannot handle the version differences, we will fail gracefully
+ * (this can happen when we have a user level daemon that is more
+ * advanced than the KVP driver.
+ *
+ * We will use values used in this handshake for determining if we have
+ * workable user level daemon and the kernel driver. We begin by taking the
+ * registration opcode out of the KVP opcode namespace. We will however,
+ * maintain compatibility with the existing user-level daemon code.
+ */
+
+/*
+ * Daemon code not supporting IP injection (legacy daemon).
+ */
+
+#define KVP_OP_REGISTER 4
+
+/*
+ * Daemon code supporting IP injection.
+ * The KVP opcode field is used to communicate the
+ * registration information; so define a namespace that
+ * will be distinct from the host defined KVP opcode.
+ */
+
+#define KVP_OP_REGISTER1 100
+
enum hv_kvp_exchg_op {
KVP_OP_GET = 0,
KVP_OP_SET,
KVP_OP_DELETE,
KVP_OP_ENUMERATE,
- KVP_OP_REGISTER,
+ KVP_OP_GET_IP_INFO,
+ KVP_OP_SET_IP_INFO,
KVP_OP_COUNT /* Number of operations, must be last. */
};
@@ -140,6 +181,26 @@ enum hv_kvp_exchg_pool {
KVP_POOL_COUNT /* Number of pools, must be last. */
};
+#define ADDR_FAMILY_NONE 0x00
+#define ADDR_FAMILY_IPV4 0x01
+#define ADDR_FAMILY_IPV6 0x02
+
+#define MAX_ADAPTER_ID_SIZE 128
+#define MAX_IP_ADDR_SIZE 1024
+#define MAX_GATEWAY_SIZE 512
+
+
+struct hv_kvp_ipaddr_value {
+ __u16 adapter_id[MAX_ADAPTER_ID_SIZE];
+ __u8 addr_family;
+ __u8 dhcp_enabled;
+ __u16 ip_addr[MAX_IP_ADDR_SIZE];
+ __u16 sub_net[MAX_IP_ADDR_SIZE];
+ __u16 gate_way[MAX_GATEWAY_SIZE];
+ __u16 dns_addr[MAX_IP_ADDR_SIZE];
+} __attribute__((packed));
+
+
struct hv_kvp_hdr {
__u8 operation;
__u8 pool;
@@ -181,16 +242,26 @@ struct hv_kvp_register {
};
struct hv_kvp_msg {
- struct hv_kvp_hdr kvp_hdr;
+ union {
+ struct hv_kvp_hdr kvp_hdr;
+ int error;
+ };
union {
struct hv_kvp_msg_get kvp_get;
struct hv_kvp_msg_set kvp_set;
struct hv_kvp_msg_delete kvp_delete;
struct hv_kvp_msg_enumerate kvp_enum_data;
+ struct hv_kvp_ipaddr_value kvp_ip_val;
struct hv_kvp_register kvp_register;
} body;
} __attribute__((packed));
+struct hv_kvp_ip_msg {
+ __u8 operation;
+ __u8 pool;
+ struct hv_kvp_ipaddr_value kvp_ip_val;
+} __attribute__((packed));
+
#ifdef __KERNEL__
#include <linux/scatterlist.h>
#include <linux/list.h>
@@ -982,6 +1053,7 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
#define HV_S_CONT 0x80070103
#define HV_ERROR_NOT_SUPPORTED 0x80070032
#define HV_ERROR_MACHINE_LOCKED 0x800704F7
+#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
/*
* While we want to handle util services as regular devices,
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index d9834b3..8fbcf7b 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -69,7 +69,7 @@ enum key_index {
};
static char kvp_send_buffer[4096];
-static char kvp_recv_buffer[4096];
+static char kvp_recv_buffer[4096 * 2];
static struct sockaddr_nl addr;
static char *os_name = "";
--
1.7.4.1
^ permalink raw reply related
* [PATCH V2 01/18] Drivers: hv: vmbus: Use the standard format string to format GUIDs
From: K. Y. Srinivasan @ 2012-08-13 17:06 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, ben
Cc: K. Y. Srinivasan
In-Reply-To: <1344877584-21738-1-git-send-email-kys@microsoft.com>
Format GUIDS as per MSFT standard. This makes interacting with MSFT
tool stack easier.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Olaf Hering <olaf@aepfle.de>
Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
---
drivers/hv/vmbus_drv.c | 38 ++------------------------------------
1 files changed, 2 insertions(+), 36 deletions(-)
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 4748086..b76e8b3 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -146,43 +146,9 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
get_channel_info(hv_dev, device_info);
if (!strcmp(dev_attr->attr.name, "class_id")) {
- ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
- device_info->chn_type.b[3],
- device_info->chn_type.b[2],
- device_info->chn_type.b[1],
- device_info->chn_type.b[0],
- device_info->chn_type.b[5],
- device_info->chn_type.b[4],
- device_info->chn_type.b[7],
- device_info->chn_type.b[6],
- device_info->chn_type.b[8],
- device_info->chn_type.b[9],
- device_info->chn_type.b[10],
- device_info->chn_type.b[11],
- device_info->chn_type.b[12],
- device_info->chn_type.b[13],
- device_info->chn_type.b[14],
- device_info->chn_type.b[15]);
+ ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b);
} else if (!strcmp(dev_attr->attr.name, "device_id")) {
- ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
- device_info->chn_instance.b[3],
- device_info->chn_instance.b[2],
- device_info->chn_instance.b[1],
- device_info->chn_instance.b[0],
- device_info->chn_instance.b[5],
- device_info->chn_instance.b[4],
- device_info->chn_instance.b[7],
- device_info->chn_instance.b[6],
- device_info->chn_instance.b[8],
- device_info->chn_instance.b[9],
- device_info->chn_instance.b[10],
- device_info->chn_instance.b[11],
- device_info->chn_instance.b[12],
- device_info->chn_instance.b[13],
- device_info->chn_instance.b[14],
- device_info->chn_instance.b[15]);
+ ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b);
} else if (!strcmp(dev_attr->attr.name, "modalias")) {
print_alias_name(hv_dev, alias_name);
ret = sprintf(buf, "vmbus:%s\n", alias_name);
--
1.7.4.1
^ permalink raw reply related
* [PATCH V2 00/18] drivers: hv: kvp
From: K. Y. Srinivasan @ 2012-08-13 17:06 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, ben
This patchset expands the KVP (Key Value Pair) functionality to
implement the mechanism to GET/SET IP addresses in the guest. This
functionality is used in Windows Server 2012 to implement VM
replication functionality. The way IP configuration information
is managed is distro specific. Based on the feedback I have gotten
from Olaf, Greg, Steve, Ben and Mairus, I have chosen to seperate
distro specific code from this patch-set. Most of the GET operation
can be implemented in a way that is completely distro independent and
I have implemented that as such and is included in this patch-set.
Some of the attributes that can only be fetched in a distro
dependent way as well the mechanism for configuring an interface
(the SET operation) that is clearly distro specific is to be
implemented via external scripts that will be invoked via the KVP
code. We define here the interface to these scripts.
Adding support for IP injection resulted in some changes to the
protocol between the user level daemon and the kernel driver.
These changes have been implemented in way that would retain
compatibility with older daemons. I would like to thank Olaf and
Greg for pointing out the compatibility issue.
This version of the patch set addresses all of the comments that I
have received to date from Olaf, Ben and others. Specifically, I have
cleanedup all of the string manipulation code. Furthermore, I have also
simplified the format of the interface configuration file that is
generated by the KVP daemon and gotten rid of some constant strings that
may not be relevant on all distros. I would like to thank Olaf and Ben
for their detailed review.
K. Y. Srinivasan (18):
Drivers: hv: vmbus: Use the standard format string to format GUIDs
Drivers: hv: Add KVP definitions for IP address injection
Drivers: hv: kvp: Cleanup error handling in KVP
Drivers: hv: kvp: Support the new IP injection messages
Tools: hv: Prepare to expand kvp_get_ip_address() functionality
Tools: hv: Further refactor kvp_get_ip_address()
Tools: hv: Gather address family information
Tools: hv: Gather subnet information
Tools: hv: Represent the ipv6 mask using CIDR notation
Tools: hv: Gather ipv[4,6] gateway information
Tools: hv: Gather DNS information
Tools: hv: Gather DHCP information
Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO
Tools: hv: Rename the function kvp_get_ip_address()
Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO
Tools: hv: Get rid of some unused variables
Tools: hv: Correctly type string variables
Tools: hv: Properly manage open streams
drivers/hv/hv_kvp.c | 253 +++++++++++--
drivers/hv/hv_util.c | 4 +-
drivers/hv/vmbus_drv.c | 38 +--
include/linux/hyperv.h | 93 +++++-
tools/hv/hv_kvp_daemon.c | 928 +++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 1147 insertions(+), 169 deletions(-)
--
1.7.4.1
^ permalink raw reply
* Re: [RFC-v2 1/6] msix: Work-around for vhost-scsi with KVM in-kernel MSI injection
From: Jan Kiszka @ 2012-08-13 12:06 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Anthony Liguori, Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin,
qemu-devel, Zhi Yong Wu, Anthony Liguori, target-devel,
Paolo Bonzini, lf-virt, Christoph Hellwig
In-Reply-To: <1344846917-7411-2-git-send-email-nab@linux-iscsi.org>
On 2012-08-13 10:35, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> This is required to get past the following assert with:
>
> commit 1523ed9e1d46b0b54540049d491475ccac7e6421
> Author: Jan Kiszka <jan.kiszka@siemens.com>
> Date: Thu May 17 10:32:39 2012 -0300
>
> virtio/vhost: Add support for KVM in-kernel MSI injection
>
> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Cc: Jan Kiszka <jan.kiszka@siemens.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Anthony Liguori <aliguori@us.ibm.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
> hw/msix.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/hw/msix.c b/hw/msix.c
> index 800fc32..c1e6dc3 100644
> --- a/hw/msix.c
> +++ b/hw/msix.c
> @@ -544,6 +544,9 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
> {
> int vector;
>
> + if (!dev->msix_vector_use_notifier && !dev->msix_vector_release_notifier)
> + return;
> +
> assert(dev->msix_vector_use_notifier &&
> dev->msix_vector_release_notifier);
>
>
I think to remember pointing out that there is a bug somewhere in the
reset code which deactivates a non-active vhost instance, no?
Jan
--
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux
^ permalink raw reply
* Re: [RFC-v2 0/6] vhost-scsi: Add support for host virtualized target
From: Michael S. Tsirkin @ 2012-08-13 9:04 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Stefan Hajnoczi, kvm-devel, Jan Kiszka, qemu-devel, Zhi Yong Wu,
Anthony Liguori, target-devel, Paolo Bonzini, lf-virt,
Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
On Mon, Aug 13, 2012 at 08:35:11AM +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> Hi Paolo, Stefan, & QEMU folks,
>
> The following is the second RFC series for vhost-scsi patches against mainline
> QEMU v1.1.0. The series is available from the following working branch:
>
> git://git.kernel.org/pub/scm/virt/kvm/nab/qemu-kvm.git vhost-scsi-merge
>
> Apologies for the delayed follow-up on this series. The changes detailed below
> addresses Paolo's original comments on vhost-scsi code from the last weeks.
Looks good overall. I sent some comments on list.
Thanks!
> As of this evening the tcm_vhost driver has now been merged into the mainline
> kernel for 3.6-rc2 here:
>
> tcm_vhost: Initial merge for vhost level target fabric driver
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=057cbf49a1f08297877
>
> Also, after following up on the qemu-kvm IRQ injection changes (from Jan) that
> caused a performance regerssion with QEMU 1.1.0 code originally reported here:
>
> vhost-scsi port to v1.1.0 + MSI-X performance regression
> http://comments.gmane.org/gmane.linux.scsi.target.devel/2277
>
> It turns out that setting explict virtio-queue IRQ affinity within guest appears
> to bring small block random IOPs performance back up to the pre IRQ injection
> conversion levels. I'm not sure why this ended up making so much of a difference
> post IRQ injection conversion, but setting virtio-queue affinity is now getting
> us back to pre IQN injection conversion levels.
>
> Changes from v1 -> v2:
>
> - Expose ABI version via VHOST_SCSI_GET_ABI_VERSION + use Rev 0 as
> starting point for v3.6-rc code (Stefan + ALiguori + nab)
> - Fix upstream qemu conflict in hw/qdev-properties.c
> - Make GET_ABI_VERSION use int (nab + mst)
> - Drop unnecessary event-notifier changes (nab)
> - Fix vhost-scsi case lables in configure (reported by paolo)
> - Convert qdev_prop_vhost_scsi to use ->get() + ->set() following
> qdev_prop_netdev (reported by paolo)
> - Fix typo in qemu-options.hx definition of vhost-scsi (reported by paolo)
> - Squash virtio-scsi: use the vhost-scsi host device from stefan (nab)
> - Fix up virtio_scsi_properties[] conflict w/ upstream qemu (nab)
> - Drop usage of to_virtio_scsi() in virtio_scsi_set_status()
> (reported by paolo)
> - Use modern VirtIOSCSIConf define in virtio-scsi.h (reported by paolo)
> - Use s->conf->vhost_scsi instead of proxyconf->vhost_scsi in
> virtio_scsi_init() (reported by paolo)
> - Only register QEMU SCSI bus is vhost-scsi is not active (reported by paolo)
> - Fix incorrect VirtIOSCSI->cmd_vqs[0] definition (nab)
>
> Please have another look, and let me know if anything else needs to be
> addressed.
>
> Thanks!
>
> --nab
>
> Nicholas Bellinger (3):
> msix: Work-around for vhost-scsi with KVM in-kernel MSI injection
> virtio-scsi: Set max_target=0 during vhost-scsi operation
> virtio-scsi: Fix incorrect VirtIOSCSI->cmd_vqs[0] definition
>
> Stefan Hajnoczi (3):
> vhost: Pass device path to vhost_dev_init()
> vhost-scsi: add -vhost-scsi host device for use with tcm-vhost
> virtio-scsi: Add start/stop functionality for vhost-scsi
>
> configure | 10 +++
> hw/Makefile.objs | 1 +
> hw/msix.c | 3 +
> hw/qdev-properties.c | 40 ++++++++++++
> hw/qdev.h | 3 +
> hw/vhost-scsi.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/vhost-scsi.h | 50 +++++++++++++++
> hw/vhost.c | 5 +-
> hw/vhost.h | 3 +-
> hw/vhost_net.c | 2 +-
> hw/virtio-pci.c | 1 +
> hw/virtio-scsi.c | 56 ++++++++++++++++-
> hw/virtio-scsi.h | 1 +
> qemu-common.h | 1 +
> qemu-config.c | 16 +++++
> qemu-options.hx | 4 +
> vl.c | 18 +++++
> 17 files changed, 378 insertions(+), 6 deletions(-)
> create mode 100644 hw/vhost-scsi.c
> create mode 100644 hw/vhost-scsi.h
>
> --
> 1.7.2.5
^ permalink raw reply
* Re: [RFC-v2 6/6] virtio-scsi: Fix incorrect VirtIOSCSI->cmd_vqs[0] definition
From: Michael S. Tsirkin @ 2012-08-13 9:02 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Stefan Hajnoczi, kvm-devel, Jan Kiszka, qemu-devel, Zhi Yong Wu,
Anthony Liguori, target-devel, Paolo Bonzini, lf-virt,
Christoph Hellwig
In-Reply-To: <1344846917-7411-7-git-send-email-nab@linux-iscsi.org>
On Mon, Aug 13, 2012 at 08:35:17AM +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> This patch fixes bug in the definition of VirtIOSCSI->cmd_vqs[0],
> where the return of virtio_add_queue() in virtio_scsi_init() ends up
> overwriting past the end of ->cmd_vqs[0].
>
> Since virtio_scsi currently assumes a single vqs for data, this patch
> simply changes ->cmd_vqs[1] to handle the single VirtQueue.
>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This is a bugfix we need even without vhost, right?
> ---
> hw/virtio-scsi.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
> index 5e2ff6b..2c70f89 100644
> --- a/hw/virtio-scsi.c
> +++ b/hw/virtio-scsi.c
> @@ -150,7 +150,7 @@ typedef struct {
> bool events_dropped;
> VirtQueue *ctrl_vq;
> VirtQueue *event_vq;
> - VirtQueue *cmd_vqs[0];
> + VirtQueue *cmd_vqs[1];
>
> bool vhost_started;
> VHostSCSI *vhost_scsi;
> --
> 1.7.2.5
^ permalink raw reply
* Re: [RFC-v2 3/6] vhost-scsi: add -vhost-scsi host device for use with tcm-vhost
From: Michael S. Tsirkin @ 2012-08-13 8:59 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Anthony Liguori, Stefan Hajnoczi, kvm-devel, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, target-devel,
Paolo Bonzini, lf-virt, Christoph Hellwig
In-Reply-To: <1344846917-7411-4-git-send-email-nab@linux-iscsi.org>
On Mon, Aug 13, 2012 at 08:35:14AM +0000, Nicholas A. Bellinger wrote:
> From: Stefan Hajnoczi <stefanha@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 using the tcm_vhost fabric driver.
>
> The tcm_vhost driver was merged into the upstream linux kernel for 3.6-rc2,
> and the commit can be found here:
>
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=057cbf49a1f08297
>
> Changelog v1 -> v2:
>
> - Expose ABI version via VHOST_SCSI_GET_ABI_VERSION + use Rev 0 as
> starting point for v3.6-rc code (Stefan + ALiguori + nab)
> - Fix upstream qemu conflict in hw/qdev-properties.c
> - Make GET_ABI_VERSION use int (nab + mst)
> - Fix vhost-scsi case lables in configure (reported by paolo)
> - Convert qdev_prop_vhost_scsi to use ->get() + ->set() following
> qdev_prop_netdev (reported by paolo)
> - Fix typo in qemu-options.hx definition of vhost-scsi (reported by paolo)
>
> 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)
>
> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> Cc: Anthony Liguori <aliguori@us.ibm.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Sent mail too fast, sorry. More comments below.
> ---
> configure | 10 +++
> hw/Makefile.objs | 1 +
> hw/qdev-properties.c | 40 ++++++++++++
> hw/qdev.h | 3 +
> hw/vhost-scsi.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/vhost-scsi.h | 50 +++++++++++++++
> qemu-common.h | 1 +
> qemu-config.c | 16 +++++
> qemu-options.hx | 4 +
> vl.c | 18 +++++
> 10 files changed, 313 insertions(+), 0 deletions(-)
> create mode 100644 hw/vhost-scsi.c
> create mode 100644 hw/vhost-scsi.h
>
> diff --git a/configure b/configure
> index f0dbc03..1f03202 100755
> --- a/configure
> +++ b/configure
> @@ -168,6 +168,7 @@ libattr=""
> xfs=""
>
> vhost_net="no"
> +vhost_scsi="no"
> kvm="no"
> gprof="no"
> debug_tcg="no"
> @@ -513,6 +514,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
> @@ -818,6 +820,10 @@ for opt do
> ;;
> --enable-vhost-net) vhost_net="yes"
> ;;
> + --disable-vhost-scsi) vhost_scsi="no"
> + ;;
> + --enable-vhost-scsi) vhost_scsi="yes"
> + ;;
> --disable-opengl) opengl="no"
> ;;
> --enable-opengl) opengl="yes"
> @@ -3116,6 +3122,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"
> @@ -3828,6 +3835,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 3ba5dd0..6ab75ec 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -169,6 +169,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 8aca0d4..0266266 100644
> --- a/hw/qdev-properties.c
> +++ b/hw/qdev-properties.c
> @@ -4,6 +4,7 @@
> #include "blockdev.h"
> #include "hw/block-common.h"
> #include "net/hub.h"
> +#include "vhost-scsi.h"
>
> void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> {
> @@ -696,6 +697,45 @@ PropertyInfo qdev_prop_vlan = {
> .set = set_vlan,
> };
>
> +/* --- vhost-scsi --- */
> +
> +static int parse_vhost_scsi_dev(DeviceState *dev, const char *str, void **ptr)
> +{
> + VHostSCSI *p;
> +
> + p = find_vhost_scsi(str);
> + if (p == NULL)
> + return -ENOENT;
> +
> + *ptr = p;
> + return 0;
> +}
> +
> +static const char *print_vhost_scsi_dev(void *ptr)
> +{
> + VHostSCSI *p = ptr;
> +
> + return (p) ? vhost_scsi_get_id(p) : "<null>";
> +}
> +
> +static void get_vhost_scsi_dev(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + get_pointer(obj, v, opaque, print_vhost_scsi_dev, name, errp);
> +}
> +
> +static void set_vhost_scsi_dev(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + set_pointer(obj, v, opaque, parse_vhost_scsi_dev, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_vhost_scsi = {
> + .name = "vhost-scsi",
> + .get = get_vhost_scsi_dev,
> + .set = set_vhost_scsi_dev,
> +};
> +
> /* --- pointer --- */
>
> /* Not a proper property, just for dirty hacks. TODO Remove it! */
Why does this make sense in the generic qdev-properties?
There's exactly one device that can use this, no?
> diff --git a/hw/qdev.h b/hw/qdev.h
> index d699194..d5873bb 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*)
>
Can this move to vhost-scsi.c?
> #define DEFINE_PROP_END_OF_LIST() \
> {}
> diff --git a/hw/vhost-scsi.c b/hw/vhost-scsi.c
> new file mode 100644
> index 0000000..7145b2d
> --- /dev/null
> +++ b/hw/vhost-scsi.c
> @@ -0,0 +1,170 @@
> +/*
> + * vhost_scsi host device
> + *
> + * Copyright IBM, Corp. 2011
> + *
> + * Authors:
> + * Stefan Hajnoczi <stefanha@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];
Could you add enum for vq numbers pls?
> + 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) {
!strcmp
> + 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, abi_version;
> + 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, &abi_version);
> + if (ret < 0) {
> + ret = -errno;
> + vhost_dev_stop(&vs->dev, vdev);
> + return ret;
> + }
> + if (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", abi_version,
> + VHOST_SCSI_ABI_VERSION);
> + ret = -ENOSYS;
> + vhost_dev_stop(&vs->dev, vdev);
> + return ret;
> + }
> + fprintf(stdout, "TCM_vHost ABI version: %d\n", 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;
> + }
> +
> + return 0;
> +}
> +
> +void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev)
> +{
> + 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);
> +
Please do not keep debugging fprintfs around.
> + ret = vhost_dev_init(&vs->dev, -1, "/dev/vhost-scsi", false);
commented on this separately
> + if (ret < 0) {
> + fprintf(stderr, "vhost-scsi: vhost initialization failed: %s\n",
> + strerror(-ret));
errors should go to monitor, here and elsewhere.
> + 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..f3096dc
> --- /dev/null
> +++ b/hw/vhost-scsi.h
> @@ -0,0 +1,50 @@
> +/*
> + * vhost_scsi host device
> + *
> + * Copyright IBM, Corp. 2011
> + *
> + * Authors:
> + * Stefan Hajnoczi <stefanha@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: July 2012 version starting point for v3.6-rc merge candidate +
> + * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
> + */
> +
> +#define VHOST_SCSI_ABI_VERSION 0
> +
> +/* 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 f9deca6..ec36002 100644
> --- a/qemu-common.h
> +++ b/qemu-common.h
> @@ -280,6 +280,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 47cb5bd..4e7a03c 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -565,6 +565,10 @@ possible drivers and properties, use @code{-device ?} and
> ETEXI
>
> DEFHEADING()
> +DEF("vhost-scsi", HAS_ARG, QEMU_OPTION_vhost_scsi,
> + "-vhost-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 91076f0..61c8284 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -144,6 +144,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
> @@ -1858,6 +1859,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;
> @@ -2617,6 +2626,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;
> @@ -3337,6 +3351,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
^ permalink raw reply
* Re: [RFC-v2 3/6] vhost-scsi: add -vhost-scsi host device for use with tcm-vhost
From: Michael S. Tsirkin @ 2012-08-13 8:53 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Anthony Liguori, Stefan Hajnoczi, kvm-devel, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, target-devel,
Paolo Bonzini, lf-virt, Christoph Hellwig
In-Reply-To: <1344846917-7411-4-git-send-email-nab@linux-iscsi.org>
On Mon, Aug 13, 2012 at 08:35:14AM +0000, Nicholas A. Bellinger wrote:
> From: Stefan Hajnoczi <stefanha@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 using the tcm_vhost fabric driver.
>
> The tcm_vhost driver was merged into the upstream linux kernel for 3.6-rc2,
> and the commit can be found here:
>
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=057cbf49a1f08297
>
> Changelog v1 -> v2:
>
> - Expose ABI version via VHOST_SCSI_GET_ABI_VERSION + use Rev 0 as
> starting point for v3.6-rc code (Stefan + ALiguori + nab)
> - Fix upstream qemu conflict in hw/qdev-properties.c
> - Make GET_ABI_VERSION use int (nab + mst)
> - Fix vhost-scsi case lables in configure (reported by paolo)
> - Convert qdev_prop_vhost_scsi to use ->get() + ->set() following
> qdev_prop_netdev (reported by paolo)
> - Fix typo in qemu-options.hx definition of vhost-scsi (reported by paolo)
>
> 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)
>
> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> Cc: Anthony Liguori <aliguori@us.ibm.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
> configure | 10 +++
> hw/Makefile.objs | 1 +
> hw/qdev-properties.c | 40 ++++++++++++
> hw/qdev.h | 3 +
> hw/vhost-scsi.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/vhost-scsi.h | 50 +++++++++++++++
> qemu-common.h | 1 +
> qemu-config.c | 16 +++++
> qemu-options.hx | 4 +
> vl.c | 18 +++++
> 10 files changed, 313 insertions(+), 0 deletions(-)
> create mode 100644 hw/vhost-scsi.c
> create mode 100644 hw/vhost-scsi.h
>
> diff --git a/configure b/configure
> index f0dbc03..1f03202 100755
> --- a/configure
> +++ b/configure
> @@ -168,6 +168,7 @@ libattr=""
> xfs=""
>
> vhost_net="no"
> +vhost_scsi="no"
> kvm="no"
> gprof="no"
> debug_tcg="no"
> @@ -513,6 +514,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
> @@ -818,6 +820,10 @@ for opt do
> ;;
> --enable-vhost-net) vhost_net="yes"
> ;;
> + --disable-vhost-scsi) vhost_scsi="no"
> + ;;
> + --enable-vhost-scsi) vhost_scsi="yes"
> + ;;
> --disable-opengl) opengl="no"
> ;;
> --enable-opengl) opengl="yes"
> @@ -3116,6 +3122,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"
> @@ -3828,6 +3835,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 3ba5dd0..6ab75ec 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -169,6 +169,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 8aca0d4..0266266 100644
> --- a/hw/qdev-properties.c
> +++ b/hw/qdev-properties.c
> @@ -4,6 +4,7 @@
> #include "blockdev.h"
> #include "hw/block-common.h"
> #include "net/hub.h"
> +#include "vhost-scsi.h"
>
> void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> {
> @@ -696,6 +697,45 @@ PropertyInfo qdev_prop_vlan = {
> .set = set_vlan,
> };
>
> +/* --- vhost-scsi --- */
> +
> +static int parse_vhost_scsi_dev(DeviceState *dev, const char *str, void **ptr)
> +{
> + VHostSCSI *p;
> +
> + p = find_vhost_scsi(str);
> + if (p == NULL)
> + return -ENOENT;
> +
> + *ptr = p;
> + return 0;
> +}
> +
> +static const char *print_vhost_scsi_dev(void *ptr)
> +{
> + VHostSCSI *p = ptr;
> +
> + return (p) ? vhost_scsi_get_id(p) : "<null>";
> +}
> +
> +static void get_vhost_scsi_dev(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + get_pointer(obj, v, opaque, print_vhost_scsi_dev, name, errp);
> +}
> +
> +static void set_vhost_scsi_dev(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + set_pointer(obj, v, opaque, parse_vhost_scsi_dev, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_vhost_scsi = {
> + .name = "vhost-scsi",
> + .get = get_vhost_scsi_dev,
> + .set = set_vhost_scsi_dev,
> +};
> +
> /* --- pointer --- */
>
> /* Not a proper property, just for dirty hacks. TODO Remove it! */
> diff --git a/hw/qdev.h b/hw/qdev.h
> index d699194..d5873bb 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..7145b2d
> --- /dev/null
> +++ b/hw/vhost-scsi.c
> @@ -0,0 +1,170 @@
> +/*
> + * vhost_scsi host device
> + *
> + * Copyright IBM, Corp. 2011
> + *
> + * Authors:
> + * Stefan Hajnoczi <stefanha@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, abi_version;
> + 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, &abi_version);
> + if (ret < 0) {
> + ret = -errno;
> + vhost_dev_stop(&vs->dev, vdev);
> + return ret;
> + }
> + if (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", abi_version,
> + VHOST_SCSI_ABI_VERSION);
> + ret = -ENOSYS;
> + vhost_dev_stop(&vs->dev, vdev);
> + return ret;
> + }
> + fprintf(stdout, "TCM_vHost ABI version: %d\n", 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;
> + }
> +
> + return 0;
> +}
> +
> +void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev)
> +{
> + 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);
This -1 is a hack. You need to support passing in fd from
the monitor, and pass it here.
> + 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..f3096dc
> --- /dev/null
> +++ b/hw/vhost-scsi.h
> @@ -0,0 +1,50 @@
> +/*
> + * vhost_scsi host device
> + *
> + * Copyright IBM, Corp. 2011
> + *
> + * Authors:
> + * Stefan Hajnoczi <stefanha@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: July 2012 version starting point for v3.6-rc merge candidate +
> + * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
> + */
> +
> +#define VHOST_SCSI_ABI_VERSION 0
> +
> +/* 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 f9deca6..ec36002 100644
> --- a/qemu-common.h
> +++ b/qemu-common.h
> @@ -280,6 +280,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 47cb5bd..4e7a03c 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -565,6 +565,10 @@ possible drivers and properties, use @code{-device ?} and
> ETEXI
>
> DEFHEADING()
> +DEF("vhost-scsi", HAS_ARG, QEMU_OPTION_vhost_scsi,
> + "-vhost-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 91076f0..61c8284 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -144,6 +144,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
> @@ -1858,6 +1859,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;
> @@ -2617,6 +2626,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;
> @@ -3337,6 +3351,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
^ permalink raw reply
* Re: [RFC-v2 1/6] msix: Work-around for vhost-scsi with KVM in-kernel MSI injection
From: Michael S. Tsirkin @ 2012-08-13 8:51 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Anthony Liguori, Stefan Hajnoczi, kvm-devel, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, target-devel,
Paolo Bonzini, lf-virt, Christoph Hellwig
In-Reply-To: <1344846917-7411-2-git-send-email-nab@linux-iscsi.org>
On Mon, Aug 13, 2012 at 08:35:12AM +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> This is required to get past the following assert with:
>
> commit 1523ed9e1d46b0b54540049d491475ccac7e6421
> Author: Jan Kiszka <jan.kiszka@siemens.com>
> Date: Thu May 17 10:32:39 2012 -0300
>
> virtio/vhost: Add support for KVM in-kernel MSI injection
>
> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Cc: Jan Kiszka <jan.kiszka@siemens.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Anthony Liguori <aliguori@us.ibm.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Could you please add a bit more explanation why
this happens with virtio scsi and why this is valid?
> ---
> hw/msix.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/hw/msix.c b/hw/msix.c
> index 800fc32..c1e6dc3 100644
> --- a/hw/msix.c
> +++ b/hw/msix.c
> @@ -544,6 +544,9 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
> {
> int vector;
>
> + if (!dev->msix_vector_use_notifier && !dev->msix_vector_release_notifier)
> + return;
> +
> assert(dev->msix_vector_use_notifier &&
> dev->msix_vector_release_notifier);
>
> --
> 1.7.2.5
^ permalink raw reply
* Re: [PATCH v7 2/4] virtio_balloon: introduce migration primitives to balloon pages
From: Michael S. Tsirkin @ 2012-08-13 8:41 UTC (permalink / raw)
To: Rafael Aquini
Cc: Rik van Riel, Konrad Rzeszutek Wilk, linux-kernel, virtualization,
linux-mm, Andi Kleen, Minchan Kim, Andrew Morton
In-Reply-To: <f19b63dfa026fe2f8f11ec017771161775744781.1344619987.git.aquini@redhat.com>
On Fri, Aug 10, 2012 at 02:55:15PM -0300, Rafael Aquini wrote:
> Memory fragmentation introduced by ballooning might reduce significantly
> the number of 2MB contiguous memory blocks that can be used within a guest,
> thus imposing performance penalties associated with the reduced number of
> transparent huge pages that could be used by the guest workload.
>
> Besides making balloon pages movable at allocation time and introducing
> the necessary primitives to perform balloon page migration/compaction,
> this patch also introduces the following locking scheme to provide the
> proper synchronization and protection for struct virtio_balloon elements
> against concurrent accesses due to parallel operations introduced by
> memory compaction / page migration.
> - balloon_lock (mutex) : synchronizes the access demand to elements of
> struct virtio_balloon and its queue operations;
> - pages_lock (spinlock): special protection to balloon pages list against
> concurrent list handling operations;
>
> Signed-off-by: Rafael Aquini <aquini@redhat.com>
> ---
> drivers/virtio/virtio_balloon.c | 138 +++++++++++++++++++++++++++++++++++++---
> include/linux/virtio_balloon.h | 4 ++
> 2 files changed, 134 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> index 0908e60..7c937a0 100644
> --- a/drivers/virtio/virtio_balloon.c
> +++ b/drivers/virtio/virtio_balloon.c
> @@ -27,6 +27,7 @@
> #include <linux/delay.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> +#include <linux/fs.h>
>
> /*
> * Balloon device works in 4K page units. So each page is pointed to by
> @@ -35,6 +36,12 @@
> */
> #define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
>
> +/* Synchronizes accesses/updates to the struct virtio_balloon elements */
> +DEFINE_MUTEX(balloon_lock);
> +
> +/* Protects 'virtio_balloon->pages' list against concurrent handling */
> +DEFINE_SPINLOCK(pages_lock);
> +
> struct virtio_balloon
> {
> struct virtio_device *vdev;
> @@ -51,6 +58,7 @@ struct virtio_balloon
>
> /* Number of balloon pages we've told the Host we're not using. */
> unsigned int num_pages;
> +
> /*
> * The pages we've told the Host we're not using.
> * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
> @@ -125,10 +133,12 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
> /* We can only do one array worth at a time. */
> num = min(num, ARRAY_SIZE(vb->pfns));
>
> + mutex_lock(&balloon_lock);
> for (vb->num_pfns = 0; vb->num_pfns < num;
> vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
> - struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
> - __GFP_NOMEMALLOC | __GFP_NOWARN);
> + struct page *page = alloc_page(GFP_HIGHUSER_MOVABLE |
> + __GFP_NORETRY | __GFP_NOWARN |
> + __GFP_NOMEMALLOC);
> if (!page) {
> if (printk_ratelimit())
> dev_printk(KERN_INFO, &vb->vdev->dev,
> @@ -141,7 +151,10 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
> set_page_pfns(vb->pfns + vb->num_pfns, page);
> vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
> totalram_pages--;
> + spin_lock(&pages_lock);
> list_add(&page->lru, &vb->pages);
If list_add above is reordered with mapping assignment below,
then nothing bad happens because balloon_mapping takes
pages_lock.
> + page->mapping = balloon_mapping;
> + spin_unlock(&pages_lock);
> }
>
> /* Didn't get any? Oh well. */
> @@ -149,6 +162,7 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
> return;
>
> tell_host(vb, vb->inflate_vq);
> + mutex_unlock(&balloon_lock);
> }
>
> static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
> @@ -169,10 +183,22 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
> /* We can only do one array worth at a time. */
> num = min(num, ARRAY_SIZE(vb->pfns));
>
> + mutex_lock(&balloon_lock);
> for (vb->num_pfns = 0; vb->num_pfns < num;
> vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
> + /*
> + * We can race against virtballoon_isolatepage() and end up
> + * stumbling across a _temporarily_ empty 'pages' list.
> + */
> + spin_lock(&pages_lock);
> + if (unlikely(list_empty(&vb->pages))) {
> + spin_unlock(&pages_lock);
> + break;
> + }
> page = list_first_entry(&vb->pages, struct page, lru);
> + page->mapping = NULL;
Unlike the case above, here
if = NULL write above is reordered with list_del below,
then isolate_page can run on a page that is not
on lru.
So I think this needs a wmb().
And maybe a comment above explaining why it is safe?
> list_del(&page->lru);
I wonder why changing page->lru here is safe against
races with unmap_and_move in the previous patch.
> + spin_unlock(&pages_lock);
> set_page_pfns(vb->pfns + vb->num_pfns, page);
> vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
> }
> @@ -182,8 +208,11 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
> * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
> * is true, we *have* to do it in this order
> */
> - tell_host(vb, vb->deflate_vq);
> - release_pages_by_pfn(vb->pfns, vb->num_pfns);
> + if (vb->num_pfns > 0) {
> + tell_host(vb, vb->deflate_vq);
> + release_pages_by_pfn(vb->pfns, vb->num_pfns);
> + }
> + mutex_unlock(&balloon_lock);
> }
>
> static inline void update_stat(struct virtio_balloon *vb, int idx,
> @@ -239,6 +268,7 @@ static void stats_handle_request(struct virtio_balloon *vb)
> struct scatterlist sg;
> unsigned int len;
>
> + mutex_lock(&balloon_lock);
> vb->need_stats_update = 0;
> update_balloon_stats(vb);
>
> @@ -249,6 +279,7 @@ static void stats_handle_request(struct virtio_balloon *vb)
> if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
> BUG();
> virtqueue_kick(vq);
> + mutex_unlock(&balloon_lock);
> }
>
> static void virtballoon_changed(struct virtio_device *vdev)
> @@ -261,22 +292,27 @@ static void virtballoon_changed(struct virtio_device *vdev)
> static inline s64 towards_target(struct virtio_balloon *vb)
> {
> __le32 v;
> - s64 target;
> + s64 target, actual;
>
> + mutex_lock(&balloon_lock);
> + actual = vb->num_pages;
> vb->vdev->config->get(vb->vdev,
> offsetof(struct virtio_balloon_config, num_pages),
> &v, sizeof(v));
> target = le32_to_cpu(v);
> - return target - vb->num_pages;
> + mutex_unlock(&balloon_lock);
> + return target - actual;
> }
>
> static void update_balloon_size(struct virtio_balloon *vb)
> {
> - __le32 actual = cpu_to_le32(vb->num_pages);
> -
> + __le32 actual;
> + mutex_lock(&balloon_lock);
> + actual = cpu_to_le32(vb->num_pages);
> vb->vdev->config->set(vb->vdev,
> offsetof(struct virtio_balloon_config, actual),
> &actual, sizeof(actual));
> + mutex_unlock(&balloon_lock);
> }
>
> static int balloon(void *_vballoon)
> @@ -339,6 +375,76 @@ static int init_vqs(struct virtio_balloon *vb)
> return 0;
> }
>
> +/*
> + * '*vb_ptr' allows virtballoon_migratepage() & virtballoon_putbackpage() to
> + * access pertinent elements from struct virtio_balloon
> + */
What if there is more than one balloon device?
> +struct virtio_balloon *vb_ptr;
> +
> +/*
> + * Populate balloon_mapping->a_ops->migratepage method to perform the balloon
> + * page migration task.
> + *
> + * After a ballooned page gets isolated by compaction procedures, this is the
> + * function that performs the page migration on behalf of move_to_new_page(),
> + * when the last calls (page)->mapping->a_ops->migratepage.
> + *
> + * Page migration for virtio balloon is done in a simple swap fashion which
> + * follows these two steps:
> + * 1) insert newpage into vb->pages list and update the host about it;
> + * 2) update the host about the removed old page from vb->pages list;
> + */
> +int virtballoon_migratepage(struct address_space *mapping,
> + struct page *newpage, struct page *page, enum migrate_mode mode)
> +{
> + mutex_lock(&balloon_lock);
> +
> + /* balloon's page migration 1st step */
> + vb_ptr->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
> + spin_lock(&pages_lock);
> + list_add(&newpage->lru, &vb_ptr->pages);
> + spin_unlock(&pages_lock);
> + set_page_pfns(vb_ptr->pfns, newpage);
> + tell_host(vb_ptr, vb_ptr->inflate_vq);
> +
> + /* balloon's page migration 2nd step */
> + vb_ptr->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
> + set_page_pfns(vb_ptr->pfns, page);
> + tell_host(vb_ptr, vb_ptr->deflate_vq);
> +
> + mutex_unlock(&balloon_lock);
> +
> + return 0;
> +}
> +
> +/*
> + * Populate balloon_mapping->a_ops->invalidatepage method to help compaction on
> + * isolating a page from the balloon page list.
> + */
> +void virtballoon_isolatepage(struct page *page, unsigned long mode)
> +{
> + spin_lock(&pages_lock);
> + list_del(&page->lru);
> + spin_unlock(&pages_lock);
> +}
> +
> +/*
> + * Populate balloon_mapping->a_ops->freepage method to help compaction on
> + * re-inserting an isolated page into the balloon page list.
> + */
> +void virtballoon_putbackpage(struct page *page)
> +{
> + spin_lock(&pages_lock);
> + list_add(&page->lru, &vb_ptr->pages);
> + spin_unlock(&pages_lock);
Could the following race trigger:
migration happens while module unloading is in progress,
module goes away between here and when the function
returns, then code for this function gets overwritten?
If yes we need locking external to module to prevent this.
Maybe add a spinlock to struct address_space?
> +}
> +
> +static const struct address_space_operations virtio_balloon_aops = {
> + .migratepage = virtballoon_migratepage,
> + .invalidatepage = virtballoon_isolatepage,
> + .freepage = virtballoon_putbackpage,
> +};
> +
> static int virtballoon_probe(struct virtio_device *vdev)
> {
> struct virtio_balloon *vb;
> @@ -351,11 +457,25 @@ static int virtballoon_probe(struct virtio_device *vdev)
> }
>
> INIT_LIST_HEAD(&vb->pages);
> +
> vb->num_pages = 0;
> init_waitqueue_head(&vb->config_change);
> init_waitqueue_head(&vb->acked);
> vb->vdev = vdev;
> vb->need_stats_update = 0;
> + vb_ptr = vb;
> +
> + /* Init the ballooned page->mapping special balloon_mapping */
> + balloon_mapping = kmalloc(sizeof(*balloon_mapping), GFP_KERNEL);
> + if (!balloon_mapping) {
> + err = -ENOMEM;
> + goto out_free_vb;
> + }
Can balloon_mapping be dereferenced at this point?
Then what happens?
> +
> + INIT_RADIX_TREE(&balloon_mapping->page_tree, GFP_ATOMIC | __GFP_NOWARN);
> + INIT_LIST_HEAD(&balloon_mapping->i_mmap_nonlinear);
> + spin_lock_init(&balloon_mapping->tree_lock);
> + balloon_mapping->a_ops = &virtio_balloon_aops;
>
> err = init_vqs(vb);
> if (err)
> @@ -373,6 +493,7 @@ out_del_vqs:
> vdev->config->del_vqs(vdev);
> out_free_vb:
> kfree(vb);
> + kfree(balloon_mapping);
No need to set it to NULL? It seems if someone else allocates a mapping
and gets this chunk of memory by chance, the logic in mm will get
confused.
> out:
> return err;
> }
> @@ -397,6 +518,7 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev)
> kthread_stop(vb->thread);
> remove_common(vb);
> kfree(vb);
> + kfree(balloon_mapping);
Neither here?
> }
>
> #ifdef CONFIG_PM
> diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h
> index 652dc8b..930f1b7 100644
> --- a/include/linux/virtio_balloon.h
> +++ b/include/linux/virtio_balloon.h
> @@ -56,4 +56,8 @@ struct virtio_balloon_stat {
> u64 val;
> } __attribute__((packed));
>
> +#if !defined(CONFIG_COMPACTION)
> +struct address_space *balloon_mapping;
> +#endif
> +
Anyone including this header will get a different copy of
balloon_mapping. Besides, need to be ifdef KERNEL.
> #endif /* _LINUX_VIRTIO_BALLOON_H */
> --
> 1.7.11.2
^ permalink raw reply
* [RFC-v2 6/6] virtio-scsi: Fix incorrect VirtIOSCSI->cmd_vqs[0] definition
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, Paolo Bonzini, lf-virt,
Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
From: Nicholas Bellinger <nab@linux-iscsi.org>
This patch fixes bug in the definition of VirtIOSCSI->cmd_vqs[0],
where the return of virtio_add_queue() in virtio_scsi_init() ends up
overwriting past the end of ->cmd_vqs[0].
Since virtio_scsi currently assumes a single vqs for data, this patch
simply changes ->cmd_vqs[1] to handle the single VirtQueue.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
hw/virtio-scsi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 5e2ff6b..2c70f89 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -150,7 +150,7 @@ typedef struct {
bool events_dropped;
VirtQueue *ctrl_vq;
VirtQueue *event_vq;
- VirtQueue *cmd_vqs[0];
+ VirtQueue *cmd_vqs[1];
bool vhost_started;
VHostSCSI *vhost_scsi;
--
1.7.2.5
^ permalink raw reply related
* [RFC-v2 5/6] virtio-scsi: Set max_target=0 during vhost-scsi operation
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, Paolo Bonzini, lf-virt,
Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
From: Nicholas Bellinger <nab@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@linux.vnet.ibm.com>
Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@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 8130956..5e2ff6b 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -545,7 +545,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
^ permalink raw reply related
* [RFC-v2 4/6] virtio-scsi: Add start/stop functionality for vhost-scsi
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, Paolo Bonzini, lf-virt,
Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This patch starts and stops vhost as the virtio device transitions
through its status phases. Vhost can only be started once the guest
reports its driver has successfully initialized, which means the
virtqueues have been set up by the guest.
v2: - Squash virtio-scsi: use the vhost-scsi host device from stefan (nab)
- Fix up virtio_scsi_properties[] conflict w/ upstream qemu (nab)
- Drop usage of to_virtio_scsi() in virtio_scsi_set_status()
(reported by paolo)
- Use modern VirtIOSCSIConf define in virtio-scsi.h (reported by paolo)
- Use s->conf->vhost_scsi instead of proxyconf->vhost_scsi in
virtio_scsi_init() (reported by paolo)
- Only register QEMU SCSI bus is vhost-scsi is not active (reported
by paolo)
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
hw/virtio-pci.c | 1 +
hw/virtio-scsi.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-scsi.h | 1 +
3 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 125eded..b29fc3b 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1036,6 +1036,7 @@ static void virtio_scsi_exit_pci(PCIDevice *pci_dev)
}
static Property virtio_scsi_properties[] = {
+ DEFINE_PROP_VHOST_SCSI("vhost-scsi", VirtIOPCIProxy, scsi.vhost_scsi),
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 5f737ac..8130956 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -13,9 +13,13 @@
*
*/
+#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>
+#include "vhost.h"
#define VIRTIO_SCSI_VQ_SIZE 128
#define VIRTIO_SCSI_CDB_SIZE 32
@@ -147,6 +151,9 @@ typedef struct {
VirtQueue *ctrl_vq;
VirtQueue *event_vq;
VirtQueue *cmd_vqs[0];
+
+ bool vhost_started;
+ VHostSCSI *vhost_scsi;
} VirtIOSCSI;
typedef struct VirtIOSCSIReq {
@@ -699,6 +706,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 = (VirtIOSCSI *)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;
@@ -712,12 +751,17 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
s->qdev = dev;
s->conf = proxyconf;
+ s->vhost_started = false;
+ s->vhost_scsi = s->conf->vhost_scsi;
/* TODO set up vdev function pointers */
s->vdev.get_config = virtio_scsi_get_config;
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);
@@ -743,5 +787,9 @@ void virtio_scsi_exit(VirtIODevice *vdev)
{
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
unregister_savevm(s->qdev, "virtio-scsi", s);
+
+ /* This will stop vhost backend if appropriate. */
+ virtio_scsi_set_status(vdev, 0);
+
virtio_cleanup(vdev);
}
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
^ permalink raw reply related
* [RFC-v2 3/6] vhost-scsi: add -vhost-scsi host device for use with tcm-vhost
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Anthony Liguori, Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin,
Jan Kiszka, qemu-devel, Zhi Yong Wu, Anthony Liguori,
Paolo Bonzini, lf-virt, Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
From: Stefan Hajnoczi <stefanha@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 using the tcm_vhost fabric driver.
The tcm_vhost driver was merged into the upstream linux kernel for 3.6-rc2,
and the commit can be found here:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=057cbf49a1f08297
Changelog v1 -> v2:
- Expose ABI version via VHOST_SCSI_GET_ABI_VERSION + use Rev 0 as
starting point for v3.6-rc code (Stefan + ALiguori + nab)
- Fix upstream qemu conflict in hw/qdev-properties.c
- Make GET_ABI_VERSION use int (nab + mst)
- Fix vhost-scsi case lables in configure (reported by paolo)
- Convert qdev_prop_vhost_scsi to use ->get() + ->set() following
qdev_prop_netdev (reported by paolo)
- Fix typo in qemu-options.hx definition of vhost-scsi (reported by paolo)
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)
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
configure | 10 +++
hw/Makefile.objs | 1 +
hw/qdev-properties.c | 40 ++++++++++++
hw/qdev.h | 3 +
hw/vhost-scsi.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/vhost-scsi.h | 50 +++++++++++++++
qemu-common.h | 1 +
qemu-config.c | 16 +++++
qemu-options.hx | 4 +
vl.c | 18 +++++
10 files changed, 313 insertions(+), 0 deletions(-)
create mode 100644 hw/vhost-scsi.c
create mode 100644 hw/vhost-scsi.h
diff --git a/configure b/configure
index f0dbc03..1f03202 100755
--- a/configure
+++ b/configure
@@ -168,6 +168,7 @@ libattr=""
xfs=""
vhost_net="no"
+vhost_scsi="no"
kvm="no"
gprof="no"
debug_tcg="no"
@@ -513,6 +514,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
@@ -818,6 +820,10 @@ for opt do
;;
--enable-vhost-net) vhost_net="yes"
;;
+ --disable-vhost-scsi) vhost_scsi="no"
+ ;;
+ --enable-vhost-scsi) vhost_scsi="yes"
+ ;;
--disable-opengl) opengl="no"
;;
--enable-opengl) opengl="yes"
@@ -3116,6 +3122,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"
@@ -3828,6 +3835,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 3ba5dd0..6ab75ec 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -169,6 +169,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 8aca0d4..0266266 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -4,6 +4,7 @@
#include "blockdev.h"
#include "hw/block-common.h"
#include "net/hub.h"
+#include "vhost-scsi.h"
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
@@ -696,6 +697,45 @@ PropertyInfo qdev_prop_vlan = {
.set = set_vlan,
};
+/* --- vhost-scsi --- */
+
+static int parse_vhost_scsi_dev(DeviceState *dev, const char *str, void **ptr)
+{
+ VHostSCSI *p;
+
+ p = find_vhost_scsi(str);
+ if (p == NULL)
+ return -ENOENT;
+
+ *ptr = p;
+ return 0;
+}
+
+static const char *print_vhost_scsi_dev(void *ptr)
+{
+ VHostSCSI *p = ptr;
+
+ return (p) ? vhost_scsi_get_id(p) : "<null>";
+}
+
+static void get_vhost_scsi_dev(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ get_pointer(obj, v, opaque, print_vhost_scsi_dev, name, errp);
+}
+
+static void set_vhost_scsi_dev(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ set_pointer(obj, v, opaque, parse_vhost_scsi_dev, name, errp);
+}
+
+PropertyInfo qdev_prop_vhost_scsi = {
+ .name = "vhost-scsi",
+ .get = get_vhost_scsi_dev,
+ .set = set_vhost_scsi_dev,
+};
+
/* --- pointer --- */
/* Not a proper property, just for dirty hacks. TODO Remove it! */
diff --git a/hw/qdev.h b/hw/qdev.h
index d699194..d5873bb 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..7145b2d
--- /dev/null
+++ b/hw/vhost-scsi.c
@@ -0,0 +1,170 @@
+/*
+ * vhost_scsi host device
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@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, abi_version;
+ 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, &abi_version);
+ if (ret < 0) {
+ ret = -errno;
+ vhost_dev_stop(&vs->dev, vdev);
+ return ret;
+ }
+ if (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", abi_version,
+ VHOST_SCSI_ABI_VERSION);
+ ret = -ENOSYS;
+ vhost_dev_stop(&vs->dev, vdev);
+ return ret;
+ }
+ fprintf(stdout, "TCM_vHost ABI version: %d\n", 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;
+ }
+
+ return 0;
+}
+
+void vhost_scsi_stop(VHostSCSI *vs, VirtIODevice *vdev)
+{
+ 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..f3096dc
--- /dev/null
+++ b/hw/vhost-scsi.h
@@ -0,0 +1,50 @@
+/*
+ * vhost_scsi host device
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@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: July 2012 version starting point for v3.6-rc merge candidate +
+ * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
+ */
+
+#define VHOST_SCSI_ABI_VERSION 0
+
+/* 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 f9deca6..ec36002 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -280,6 +280,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 47cb5bd..4e7a03c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -565,6 +565,10 @@ possible drivers and properties, use @code{-device ?} and
ETEXI
DEFHEADING()
+DEF("vhost-scsi", HAS_ARG, QEMU_OPTION_vhost_scsi,
+ "-vhost-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 91076f0..61c8284 100644
--- a/vl.c
+++ b/vl.c
@@ -144,6 +144,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
@@ -1858,6 +1859,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;
@@ -2617,6 +2626,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;
@@ -3337,6 +3351,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
^ permalink raw reply related
* [RFC-v2 2/6] vhost: Pass device path to vhost_dev_init()
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, Paolo Bonzini, lf-virt,
Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
From: Stefan Hajnoczi <stefanha@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@linux.vnet.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@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 ecaa22d..df2c4a3 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -109,7 +109,7 @@ struct vhost_net *vhost_net_init(NetClientState *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
^ permalink raw reply related
* [RFC-v2 1/6] msix: Work-around for vhost-scsi with KVM in-kernel MSI injection
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Anthony Liguori, Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin,
Jan Kiszka, qemu-devel, Zhi Yong Wu, Anthony Liguori,
Paolo Bonzini, lf-virt, Christoph Hellwig
In-Reply-To: <1344846917-7411-1-git-send-email-nab@linux-iscsi.org>
From: Nicholas Bellinger <nab@linux-iscsi.org>
This is required to get past the following assert with:
commit 1523ed9e1d46b0b54540049d491475ccac7e6421
Author: Jan Kiszka <jan.kiszka@siemens.com>
Date: Thu May 17 10:32:39 2012 -0300
virtio/vhost: Add support for KVM in-kernel MSI injection
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
hw/msix.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index 800fc32..c1e6dc3 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -544,6 +544,9 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
{
int vector;
+ if (!dev->msix_vector_use_notifier && !dev->msix_vector_release_notifier)
+ return;
+
assert(dev->msix_vector_use_notifier &&
dev->msix_vector_release_notifier);
--
1.7.2.5
^ permalink raw reply related
* [RFC-v2 0/6] vhost-scsi: Add support for host virtualized target
From: Nicholas A. Bellinger @ 2012-08-13 8:35 UTC (permalink / raw)
To: target-devel
Cc: Stefan Hajnoczi, kvm-devel, Michael S. Tsirkin, Jan Kiszka,
qemu-devel, Zhi Yong Wu, Anthony Liguori, Paolo Bonzini, lf-virt,
Christoph Hellwig
From: Nicholas Bellinger <nab@linux-iscsi.org>
Hi Paolo, Stefan, & QEMU folks,
The following is the second RFC series for vhost-scsi patches against mainline
QEMU v1.1.0. The series is available from the following working branch:
git://git.kernel.org/pub/scm/virt/kvm/nab/qemu-kvm.git vhost-scsi-merge
Apologies for the delayed follow-up on this series. The changes detailed below
addresses Paolo's original comments on vhost-scsi code from the last weeks.
As of this evening the tcm_vhost driver has now been merged into the mainline
kernel for 3.6-rc2 here:
tcm_vhost: Initial merge for vhost level target fabric driver
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=057cbf49a1f08297877
Also, after following up on the qemu-kvm IRQ injection changes (from Jan) that
caused a performance regerssion with QEMU 1.1.0 code originally reported here:
vhost-scsi port to v1.1.0 + MSI-X performance regression
http://comments.gmane.org/gmane.linux.scsi.target.devel/2277
It turns out that setting explict virtio-queue IRQ affinity within guest appears
to bring small block random IOPs performance back up to the pre IRQ injection
conversion levels. I'm not sure why this ended up making so much of a difference
post IRQ injection conversion, but setting virtio-queue affinity is now getting
us back to pre IQN injection conversion levels.
Changes from v1 -> v2:
- Expose ABI version via VHOST_SCSI_GET_ABI_VERSION + use Rev 0 as
starting point for v3.6-rc code (Stefan + ALiguori + nab)
- Fix upstream qemu conflict in hw/qdev-properties.c
- Make GET_ABI_VERSION use int (nab + mst)
- Drop unnecessary event-notifier changes (nab)
- Fix vhost-scsi case lables in configure (reported by paolo)
- Convert qdev_prop_vhost_scsi to use ->get() + ->set() following
qdev_prop_netdev (reported by paolo)
- Fix typo in qemu-options.hx definition of vhost-scsi (reported by paolo)
- Squash virtio-scsi: use the vhost-scsi host device from stefan (nab)
- Fix up virtio_scsi_properties[] conflict w/ upstream qemu (nab)
- Drop usage of to_virtio_scsi() in virtio_scsi_set_status()
(reported by paolo)
- Use modern VirtIOSCSIConf define in virtio-scsi.h (reported by paolo)
- Use s->conf->vhost_scsi instead of proxyconf->vhost_scsi in
virtio_scsi_init() (reported by paolo)
- Only register QEMU SCSI bus is vhost-scsi is not active (reported by paolo)
- Fix incorrect VirtIOSCSI->cmd_vqs[0] definition (nab)
Please have another look, and let me know if anything else needs to be
addressed.
Thanks!
--nab
Nicholas Bellinger (3):
msix: Work-around for vhost-scsi with KVM in-kernel MSI injection
virtio-scsi: Set max_target=0 during vhost-scsi operation
virtio-scsi: Fix incorrect VirtIOSCSI->cmd_vqs[0] definition
Stefan Hajnoczi (3):
vhost: Pass device path to vhost_dev_init()
vhost-scsi: add -vhost-scsi host device for use with tcm-vhost
virtio-scsi: Add start/stop functionality for vhost-scsi
configure | 10 +++
hw/Makefile.objs | 1 +
hw/msix.c | 3 +
hw/qdev-properties.c | 40 ++++++++++++
hw/qdev.h | 3 +
hw/vhost-scsi.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/vhost-scsi.h | 50 +++++++++++++++
hw/vhost.c | 5 +-
hw/vhost.h | 3 +-
hw/vhost_net.c | 2 +-
hw/virtio-pci.c | 1 +
hw/virtio-scsi.c | 56 ++++++++++++++++-
hw/virtio-scsi.h | 1 +
qemu-common.h | 1 +
qemu-config.c | 16 +++++
qemu-options.hx | 4 +
vl.c | 18 +++++
17 files changed, 378 insertions(+), 6 deletions(-)
create mode 100644 hw/vhost-scsi.c
create mode 100644 hw/vhost-scsi.h
--
1.7.2.5
^ permalink raw reply
* Re: [PATCH v7 1/4] mm: introduce compaction and migration for virtio ballooned pages
From: Michael S. Tsirkin @ 2012-08-13 8:26 UTC (permalink / raw)
To: Rafael Aquini
Cc: Rik van Riel, Konrad Rzeszutek Wilk, linux-kernel, virtualization,
linux-mm, Andi Kleen, Minchan Kim, Andrew Morton
In-Reply-To: <292b1b52e863a05b299f94bda69a61371011ac19.1344619987.git.aquini@redhat.com>
On Fri, Aug 10, 2012 at 02:55:14PM -0300, Rafael Aquini wrote:
> Memory fragmentation introduced by ballooning might reduce significantly
> the number of 2MB contiguous memory blocks that can be used within a guest,
> thus imposing performance penalties associated with the reduced number of
> transparent huge pages that could be used by the guest workload.
>
> This patch introduces the helper functions as well as the necessary changes
> to teach compaction and migration bits how to cope with pages which are
> part of a guest memory balloon, in order to make them movable by memory
> compaction procedures.
>
> Signed-off-by: Rafael Aquini <aquini@redhat.com>
> ---
> include/linux/mm.h | 17 ++++++++
> mm/compaction.c | 125 +++++++++++++++++++++++++++++++++++++++++++++--------
> mm/migrate.c | 30 ++++++++++++-
> 3 files changed, 152 insertions(+), 20 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 311be90..56cc553 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1662,5 +1662,22 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; }
> static inline bool page_is_guard(struct page *page) { return false; }
> #endif /* CONFIG_DEBUG_PAGEALLOC */
>
> +#if (defined(CONFIG_VIRTIO_BALLOON) || \
> + defined(CONFIG_VIRTIO_BALLOON_MODULE)) && defined(CONFIG_COMPACTION)
> +extern bool isolate_balloon_page(struct page *);
> +extern void putback_balloon_page(struct page *);
> +extern struct address_space *balloon_mapping;
> +
> +static inline bool movable_balloon_page(struct page *page)
> +{
> + return (page->mapping && page->mapping == balloon_mapping);
I am guessing this needs smp_read_barrier_depends, and maybe
ACCESS_ONCE ...
> +}
> +
> +#else
> +static inline bool isolate_balloon_page(struct page *page) { return false; }
> +static inline void putback_balloon_page(struct page *page) { return false; }
> +static inline bool movable_balloon_page(struct page *page) { return false; }
> +#endif /* (VIRTIO_BALLOON || VIRTIO_BALLOON_MODULE) && CONFIG_COMPACTION */
> +
This does mean that only one type of balloon is useable at a time.
I wonder whether using a flag in address_space structure instead
is possible ...
> #endif /* __KERNEL__ */
> #endif /* _LINUX_MM_H */
> diff --git a/mm/compaction.c b/mm/compaction.c
> index e78cb96..e4e871b 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -14,6 +14,7 @@
> #include <linux/backing-dev.h>
> #include <linux/sysctl.h>
> #include <linux/sysfs.h>
> +#include <linux/export.h>
> #include "internal.h"
>
> #if defined CONFIG_COMPACTION || defined CONFIG_CMA
> @@ -21,6 +22,84 @@
> #define CREATE_TRACE_POINTS
> #include <trace/events/compaction.h>
>
> +#if defined(CONFIG_VIRTIO_BALLOON) || defined(CONFIG_VIRTIO_BALLOON_MODULE)
> +/*
> + * Balloon pages special page->mapping.
> + * Users must properly allocate and initialize an instance of balloon_mapping,
> + * and set it as the page->mapping for balloon enlisted page instances.
> + * There is no need on utilizing struct address_space locking schemes for
> + * balloon_mapping as, once it gets initialized at balloon driver, it will
> + * remain just like a static reference that helps us on identifying a guest
> + * ballooned page by its mapping, as well as it will keep the 'a_ops' callback
> + * pointers to the functions that will execute the balloon page mobility tasks.
> + *
> + * address_space_operations necessary methods for ballooned pages:
> + * .migratepage - used to perform balloon's page migration (as is)
> + * .invalidatepage - used to isolate a page from balloon's page list
> + * .freepage - used to reinsert an isolated page to balloon's page list
> + */
> +struct address_space *balloon_mapping;
> +EXPORT_SYMBOL_GPL(balloon_mapping);
> +
> +static inline void __isolate_balloon_page(struct page *page)
> +{
> + page->mapping->a_ops->invalidatepage(page, 0);
> +}
> +
> +static inline void __putback_balloon_page(struct page *page)
> +{
> + page->mapping->a_ops->freepage(page);
> +}
> +
> +/* __isolate_lru_page() counterpart for a ballooned page */
> +bool isolate_balloon_page(struct page *page)
> +{
> + if (WARN_ON(!movable_balloon_page(page)))
Looks like this actually can happen if the page is leaked
between previous movable_balloon_page and here.
> + return false;
> +
> + if (likely(get_page_unless_zero(page))) {
> + /*
> + * As balloon pages are not isolated from LRU lists, concurrent
> + * compaction threads can race against page migration functions
> + * move_to_new_page() & __unmap_and_move().
> + * In order to avoid having an already isolated balloon page
> + * being (wrongly) re-isolated while it is under migration,
> + * lets be sure we have the page lock before proceeding with
> + * the balloon page isolation steps.
> + */
> + if (likely(trylock_page(page))) {
> + /*
> + * A ballooned page, by default, has just one refcount.
> + * Prevent concurrent compaction threads from isolating
> + * an already isolated balloon page.
> + */
> + if (movable_balloon_page(page) &&
> + (page_count(page) == 2)) {
> + __isolate_balloon_page(page);
> + unlock_page(page);
> + return true;
> + }
> + unlock_page(page);
> + }
> + /* Drop refcount taken for this already isolated page */
> + put_page(page);
> + }
> + return false;
> +}
> +
> +/* putback_lru_page() counterpart for a ballooned page */
> +void putback_balloon_page(struct page *page)
> +{
> + if (WARN_ON(!movable_balloon_page(page)))
> + return;
> +
> + lock_page(page);
> + __putback_balloon_page(page);
> + put_page(page);
> + unlock_page(page);
> +}
> +#endif /* CONFIG_VIRTIO_BALLOON || CONFIG_VIRTIO_BALLOON_MODULE */
> +
> static unsigned long release_freepages(struct list_head *freelist)
> {
> struct page *page, *next;
> @@ -312,32 +391,40 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
> continue;
> }
>
> - if (!PageLRU(page))
> - continue;
> -
> /*
> - * PageLRU is set, and lru_lock excludes isolation,
> - * splitting and collapsing (collapsing has already
> - * happened if PageLRU is set).
> + * It is possible to migrate LRU pages and balloon pages.
> + * Skip any other type of page.
> */
> - if (PageTransHuge(page)) {
> - low_pfn += (1 << compound_order(page)) - 1;
> - continue;
> - }
> + if (PageLRU(page)) {
> + /*
> + * PageLRU is set, and lru_lock excludes isolation,
> + * splitting and collapsing (collapsing has already
> + * happened if PageLRU is set).
> + */
> + if (PageTransHuge(page)) {
> + low_pfn += (1 << compound_order(page)) - 1;
> + continue;
> + }
>
> - if (!cc->sync)
> - mode |= ISOLATE_ASYNC_MIGRATE;
> + if (!cc->sync)
> + mode |= ISOLATE_ASYNC_MIGRATE;
>
> - lruvec = mem_cgroup_page_lruvec(page, zone);
> + lruvec = mem_cgroup_page_lruvec(page, zone);
>
> - /* Try isolate the page */
> - if (__isolate_lru_page(page, mode) != 0)
> - continue;
> + /* Try isolate the page */
> + if (__isolate_lru_page(page, mode) != 0)
> + continue;
> +
> + VM_BUG_ON(PageTransCompound(page));
>
> - VM_BUG_ON(PageTransCompound(page));
> + /* Successfully isolated */
> + del_page_from_lru_list(page, lruvec, page_lru(page));
> + } else if (unlikely(movable_balloon_page(page))) {
> + if (!isolate_balloon_page(page))
> + continue;
> + } else
> + continue;
>
> - /* Successfully isolated */
> - del_page_from_lru_list(page, lruvec, page_lru(page));
> list_add(&page->lru, migratelist);
> cc->nr_migratepages++;
> nr_isolated++;
> diff --git a/mm/migrate.c b/mm/migrate.c
> index 77ed2d7..80f22bb 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
> @@ -79,7 +79,10 @@ void putback_lru_pages(struct list_head *l)
> list_del(&page->lru);
> dec_zone_page_state(page, NR_ISOLATED_ANON +
> page_is_file_cache(page));
> - putback_lru_page(page);
> + if (unlikely(movable_balloon_page(page)))
> + putback_balloon_page(page);
> + else
> + putback_lru_page(page);
> }
> }
>
> @@ -778,6 +781,17 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
> }
> }
>
> + if (unlikely(movable_balloon_page(page))) {
> + /*
> + * A ballooned page does not need any special attention from
> + * physical to virtual reverse mapping procedures.
> + * Skip any attempt to unmap PTEs or to remap swap cache,
> + * in order to avoid burning cycles at rmap level.
> + */
> + remap_swapcache = 0;
> + goto skip_unmap;
> + }
> +
> /*
> * Corner case handling:
> * 1. When a new swap-cache page is read into, it is added to the LRU
> @@ -846,6 +860,20 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
> goto out;
>
> rc = __unmap_and_move(page, newpage, force, offlining, mode);
> +
> + if (unlikely(movable_balloon_page(newpage))) {
> + /*
> + * A ballooned page has been migrated already. Now, it is the
> + * time to wrap-up counters, handle the old page back to Buddy
> + * and return.
> + */
> + list_del(&page->lru);
> + dec_zone_page_state(page, NR_ISOLATED_ANON +
> + page_is_file_cache(page));
> + put_page(page);
> + __free_page(page);
> + return rc;
> + }
> out:
> if (rc != -EAGAIN) {
> /*
> --
> 1.7.11.2
^ permalink raw reply
* Re: [Question]About KVM network zero-copy feature!
From: Michael S. Tsirkin @ 2012-08-13 7:18 UTC (permalink / raw)
To: Peter Huang(Peng)
Cc: xiaohui.xin, kvm, netdev, virtualization, avi, Stephen Hemminger
In-Reply-To: <50285766.50307@huawei.com>
Last patchset version was this:
[PATCH v16 00/17] Provide a zero-copy method on KVM virtio-net
IIRC the main issue was the need to integrate the patchset with
macvtap (as opposed to using a separate device).
On Mon, Aug 13, 2012 at 09:24:54AM +0800, Peter Huang(Peng) wrote:
> Hi, Michael
>
> IIt will be usefull if we can implement rx zero-copy, could you give
> me some help if you know some technical details or some
> references on the internet?
>
> I am wondering may be I can take a deep look on it first then decide
> if I can take it over or not.
>
> Thanks a lot.
>
> On 2012/8/12 17:37, Michael S. Tsirkin wrote:
> > On Sat, Aug 11, 2012 at 08:42:44PM -0400, Robert Vineyard wrote:
> >> (adding Xin Xiaohui to the conversation for comment)
> >>
> >> According to the NetworkingTodo page on the KVM wiki, zero-copy RX
> >> for macvtap is in fact on the roadmap, assigned to Xin:
> >>
> >> http://www.linux-kvm.org/page/NetworkingTodo
> > AFAIK Xin left Intel and is not working on it.
> > Contributions are welcome.
> >
^ permalink raw reply
* Re: [Question]About KVM network zero-copy feature!
From: Robert Vineyard @ 2012-08-13 5:59 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: xiaohui.xin, kvm, netdev, Peter Huang(Peng), virtualization, avi,
Stephen Hemminger
In-Reply-To: <50287857.2060305@tuffmail.com>
On 08/12/2012 11:45 PM, Robert Vineyard wrote:
> On 08/12/2012 05:37 AM, Michael S. Tsirkin wrote:
>> Contributions are welcome.
>
> That's too bad... do you know of anyone else (at Intel or otherwise) who
> might be familiar enough with the existing codebase to get me started?
I suppose I should have done my homework... *ahem* time for me to finish
RTFM on git...
I'll come back after digging through more kernel code :-)
-- Robert
^ permalink raw reply
* Re: [Question]About KVM network zero-copy feature!
From: Robert Vineyard @ 2012-08-13 3:45 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: xiaohui.xin, kvm, netdev, Peter Huang(Peng), virtualization, avi,
Stephen Hemminger
In-Reply-To: <20120812093730.GD1421@redhat.com>
On 08/12/2012 05:37 AM, Michael S. Tsirkin wrote:
> AFAIK Xin left Intel and is not working on it.
> Contributions are welcome.
That's too bad... do you know of anyone else (at Intel or otherwise) who
might be familiar enough with the existing codebase to get me started?
From the code I've looked at, it appears that among other things
they're using the splice(2) / vmsplice(2) system calls to effect
"copying" without actually copying data. If I understand the semantics
correctly, these calls are basically shuffling pointers around to avoid
unnecessary memcpy(3) / mmap(2) calls. I've even seen a "zero-copy"
version of sendfile(2) that essentially wraps it around a call to splice(2).
I may be able to hack something together based on the current zero-copy
TX implementation, but as I'm still wrapping my head around several of
the concepts I just described, it may be awhile before I can produce
anything useful. I have quite a bit of experience developing for Linux
in C, but this would be my first attempt at writing kernel/device-driver
code.
>> The Release Notes for RHEL 6.2 (originally published on 12/06/2011)
>> also specifically mention macvtap/vhost zero-copy capabilities as
>> being included as a Technology Preview:
>>
>> http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/6.2_Release_Notes/virtualization.html
>
> I think this means TX.
It does. I meant to clarify that point in my original email... yes, only
TX zero-copy is currently implemented, and it is still marked as
"experimental". Outside of the custom solutions like PF_RING that I
mentioned, I don't know that I've seen zero-copy for RX.
-- Robert Vineyard
^ permalink raw reply
* Re: [Question]About KVM network zero-copy feature!
From: Peter Huang(Peng) @ 2012-08-13 1:24 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: xiaohui.xin, kvm, netdev, virtualization, avi, Stephen Hemminger
In-Reply-To: <20120812093730.GD1421@redhat.com>
Hi, Michael
IIt will be usefull if we can implement rx zero-copy, could you give
me some help if you know some technical details or some
references on the internet?
I am wondering may be I can take a deep look on it first then decide
if I can take it over or not.
Thanks a lot.
On 2012/8/12 17:37, Michael S. Tsirkin wrote:
> On Sat, Aug 11, 2012 at 08:42:44PM -0400, Robert Vineyard wrote:
>> (adding Xin Xiaohui to the conversation for comment)
>>
>> According to the NetworkingTodo page on the KVM wiki, zero-copy RX
>> for macvtap is in fact on the roadmap, assigned to Xin:
>>
>> http://www.linux-kvm.org/page/NetworkingTodo
> AFAIK Xin left Intel and is not working on it.
> Contributions are welcome.
>
^ permalink raw reply
* Re: [PATCH V2 0/6] virtio-trace: Support virtio-trace
From: Rusty Russell @ 2012-08-12 23:28 UTC (permalink / raw)
To: Yoshihiro YUNOMAE, linux-kernel
Cc: Herbert Xu, Arnd Bergmann, Frederic Weisbecker, yrl.pp-manager.tt,
qemu-devel, Borislav Petkov, virtualization, Masami Hiramatsu,
Franch Ch. Eigler, Ingo Molnar, Mathieu Desnoyers, Steven Rostedt,
Anthony Liguori, Greg Kroah-Hartman, Amit Shah
In-Reply-To: <20120809123029.8542.38311.stgit@ltc189.sdl.hitachi.co.jp>
On Thu, 09 Aug 2012 21:30:29 +0900, Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com> wrote:
> Hi All,
>
> The following patch set provides a low-overhead system for collecting kernel
> tracing data of guests by a host in a virtualization environment.
Thankyou!
I've applied this, and it will head into linux-next in the next few
days.
Cheers,
Rusty.
^ permalink raw reply
* Re: [PATCH v7 3/4] mm: introduce putback_movable_pages()
From: Minchan Kim @ 2012-08-12 23:26 UTC (permalink / raw)
To: Rafael Aquini
Cc: Rik van Riel, Konrad Rzeszutek Wilk, Michael S. Tsirkin,
linux-kernel, virtualization, linux-mm, Andi Kleen, Andrew Morton
In-Reply-To: <9147e5cccc4bb2d3f2e5f155e640148eb5365af5.1344619987.git.aquini@redhat.com>
On Fri, Aug 10, 2012 at 02:55:16PM -0300, Rafael Aquini wrote:
> The PATCH "mm: introduce compaction and migration for virtio ballooned pages"
> hacks around putback_lru_pages() in order to allow ballooned pages to be
> re-inserted on balloon page list as if a ballooned page was like a LRU page.
>
> As ballooned pages are not legitimate LRU pages, this patch introduces
> putback_movable_pages() to properly cope with cases where the isolated
> pageset contains ballooned pages and LRU pages, thus fixing the mentioned
> inelegant hack around putback_lru_pages().
>
> Signed-off-by: Rafael Aquini <aquini@redhat.com>
Reviewed-by: Minchan Kim <minchan@kernel.org>
Thanks for your good work, Rafael.
--
Kind regards,
Minchan Kim
^ permalink raw reply
* Re: [PATCH v7 1/4] mm: introduce compaction and migration for virtio ballooned pages
From: Minchan Kim @ 2012-08-12 23:14 UTC (permalink / raw)
To: Rafael Aquini
Cc: Rik van Riel, Konrad Rzeszutek Wilk, Michael S. Tsirkin,
linux-kernel, virtualization, linux-mm, Andi Kleen, Andrew Morton
In-Reply-To: <292b1b52e863a05b299f94bda69a61371011ac19.1344619987.git.aquini@redhat.com>
On Fri, Aug 10, 2012 at 02:55:14PM -0300, Rafael Aquini wrote:
> Memory fragmentation introduced by ballooning might reduce significantly
> the number of 2MB contiguous memory blocks that can be used within a guest,
> thus imposing performance penalties associated with the reduced number of
> transparent huge pages that could be used by the guest workload.
>
> This patch introduces the helper functions as well as the necessary changes
> to teach compaction and migration bits how to cope with pages which are
> part of a guest memory balloon, in order to make them movable by memory
> compaction procedures.
>
> Signed-off-by: Rafael Aquini <aquini@redhat.com>
Reviewed-by: Minchan Kim <minchan@kernel.org>
--
Kind regards,
Minchan Kim
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox