2016-05-03 09:45:05 +02:00
|
|
|
Subject: [PATCH v12 1/2] libxl: add support for vscsi
|
|
|
|
Date: Wed, 13 Apr 2016 08:56:59 +0000
|
|
|
|
Message-Id: <1460537820-15398-2-git-send-email-olaf@aepfle.de>
|
2014-05-13 19:13:17 +02:00
|
|
|
fate#316613 , https://fate.suse.com/316613
|
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
Port pvscsi support from xend to libxl:
|
|
|
|
|
|
|
|
vscsi=['pdev,vdev{,options}']
|
|
|
|
xl scsi-attach
|
|
|
|
xl scsi-detach
|
|
|
|
xl scsi-list
|
|
|
|
|
|
|
|
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
|
|
|
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
|
|
|
|
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
|
|
|
Cc: Ian Campbell <ian.campbell@citrix.com>
|
|
|
|
Cc: Wei Liu <wei.liu2@citrix.com>
|
|
|
|
---
|
|
|
|
docs/man/xl.cfg.pod.5 | 56 +
|
|
|
|
docs/man/xl.pod.1 | 18
|
|
|
|
tools/libxl/Makefile | 2
|
|
|
|
tools/libxl/libxl.c | 9
|
|
|
|
tools/libxl/libxl.h | 42 +
|
|
|
|
tools/libxl/libxl_create.c | 41 +
|
|
|
|
tools/libxl/libxl_device.c | 2
|
|
|
|
tools/libxl/libxl_internal.h | 8
|
|
|
|
tools/libxl/libxl_types.idl | 53 +
|
|
|
|
tools/libxl/libxl_types_internal.idl | 1
|
|
|
|
tools/libxl/libxl_vscsi.c | 1169 +++++++++++++++++++++++++++++++++++
|
|
|
|
tools/libxl/libxlu_vscsi.c | 667 +++++++++++++++++++
|
|
|
|
tools/libxl/libxlutil.h | 19
|
|
|
|
tools/libxl/xl.h | 3
|
|
|
|
tools/libxl/xl_cmdimpl.c | 225 ++++++
|
|
|
|
tools/libxl/xl_cmdtable.c | 15
|
|
|
|
16 files changed, 2326 insertions(+), 4 deletions(-)
|
|
|
|
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/docs/man/xl.cfg.pod.5
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/docs/man/xl.cfg.pod.5
|
|
|
|
+++ xen-4.7.0-testing/docs/man/xl.cfg.pod.5
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -517,6 +517,62 @@ value is optional if this is a guest dom
|
2014-05-13 19:13:17 +02:00
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
+=item B<vscsi=[ "VSCSI_SPEC_STRING", "VSCSI_SPEC_STRING", ...]>
|
|
|
|
+
|
|
|
|
+Specifies the PVSCSI devices to be provided to the guest. PVSCSI passes
|
2016-05-03 09:45:05 +02:00
|
|
|
+SCSI devices from the backend domain to the guest.
|
|
|
|
+
|
|
|
|
+Each VSCSI_SPEC_STRING consists of "pdev,vdev[,options]".
|
|
|
|
+'pdev' describes the physical device, preferable in a persistent format
|
|
|
|
+such as /dev/disk/by-*/*.
|
|
|
|
+'vdev' is the domU device in vHOST:CHANNEL:TARGET:LUN notation, all integers.
|
|
|
|
+'options' lists additional flags which a backend may recognize.
|
|
|
|
+
|
|
|
|
+The supported values for "pdev" and "options" depends on the backend driver used:
|
|
|
|
+
|
|
|
|
+=over 4
|
|
|
|
+
|
|
|
|
+=item B<Linux>
|
|
|
|
+
|
|
|
|
+=over 4
|
|
|
|
+
|
|
|
|
+=item C<pdev>
|
|
|
|
+
|
|
|
|
+The backend driver in the pvops kernel is part of the Linux-IO Target framework
|
|
|
|
+(LIO). As such the SCSI devices have to be configured first with the tools
|
|
|
|
+provided by this framework, such as a xen-scsiback aware targetcli. The "pdev"
|
|
|
|
+in domU.cfg has to refer to a config item in that framework instead of the raw
|
|
|
|
+device. Usually this is a WWN in the form of "naa.WWN:LUN".
|
|
|
|
+
|
|
|
|
+=item C<options>
|
|
|
|
+
|
|
|
|
+No options recognized.
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+=back
|
|
|
|
+
|
|
|
|
+=item B<Linux based on classic Xen kernel>
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+=over 4
|
|
|
|
+
|
|
|
|
+=item C<pdev>
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+The dom0 device in either /dev/scsidev or pHOST:CHANNEL:TARGET:LUN notation.
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+It's recommended to use persistent names "/dev/disk/by-*/*" to refer to a "pdev".
|
|
|
|
+The toolstack will translate this internally to "h:c:t:l" notation, which is how
|
|
|
|
+the backend driver will access the device. Using the "h:c:t:l" notation for
|
|
|
|
+"pdev" in domU.cfg is discouraged because this value will change across reboots,
|
|
|
|
+depending on the detection order in the OS.
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+=item C<options>
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+Currently only the option value "feature-host" is recognized. SCSI command
|
|
|
|
+emulation in backend driver is bypassed when "feature-host" is specified.
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+=back
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+=back
|
|
|
|
+
|
|
|
|
=item B<vfb=[ "VFB_SPEC_STRING", "VFB_SPEC_STRING", ...]>
|
|
|
|
|
|
|
|
Specifies the paravirtual framebuffer devices which should be supplied
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/docs/man/xl.pod.1
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/docs/man/xl.pod.1
|
|
|
|
+++ xen-4.7.0-testing/docs/man/xl.pod.1
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -1423,6 +1423,24 @@ List virtual trusted platform modules fo
|
2014-05-13 19:13:17 +02:00
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
+=head2 PVSCSI DEVICES
|
|
|
|
+
|
|
|
|
+=over 4
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+=item B<scsi-attach> I<domain-id> I<pdev> I<vdev>,I<[feature-host]>
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+Creates a new vscsi device in the domain specified by I<domain-id>.
|
|
|
|
+
|
|
|
|
+=item B<scsi-detach> I<domain-id> I<vdev>
|
|
|
|
+
|
|
|
|
+Removes the vscsi device from domain specified by I<domain-id>.
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+=item B<scsi-list> I<domain-id> I<[domain-id] ...>
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+List vscsi devices for the domain specified by I<domain-id>.
|
|
|
|
+
|
|
|
|
+=back
|
|
|
|
+
|
|
|
|
=head1 PCI PASS-THROUGH
|
|
|
|
|
|
|
|
=over 4
|
2016-05-03 09:45:05 +02:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/Makefile
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/Makefile
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/Makefile
|
|
|
|
@@ -108,6 +108,7 @@ endif
|
|
|
|
LIBXL_LIBS += -lyajl
|
|
|
|
|
|
|
|
LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
|
|
|
|
+ libxl_vscsi.o \
|
|
|
|
libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o \
|
|
|
|
libxl_internal.o libxl_utils.o libxl_uuid.o \
|
|
|
|
libxl_json.o libxl_aoutils.o libxl_numa.o libxl_vnuma.o \
|
|
|
|
@@ -151,6 +152,7 @@ AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
|
|
|
|
AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
|
|
|
|
AUTOSRCS += _libxl_save_msgs_callout.c _libxl_save_msgs_helper.c
|
|
|
|
LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o \
|
|
|
|
+ libxlu_vscsi.o \
|
|
|
|
libxlu_disk_l.o libxlu_disk.o libxlu_vif.o libxlu_pci.o
|
|
|
|
$(LIBXLU_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h
|
|
|
|
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl.c
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl.c
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl.c
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -4326,6 +4326,7 @@ DEFINE_DEVICE_REMOVE_CUSTOM(usbctrl, des
|
2016-05-03 09:45:05 +02:00
|
|
|
/* The following functions are defined:
|
|
|
|
* libxl_device_disk_add
|
|
|
|
* libxl_device_nic_add
|
|
|
|
+ * libxl_device_vscsictrl_add
|
2014-05-13 19:13:17 +02:00
|
|
|
* libxl_device_vtpm_add
|
2016-03-25 23:10:02 +01:00
|
|
|
* libxl_device_usbctrl_add
|
|
|
|
* libxl_device_usbdev_add
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -4357,6 +4358,9 @@ DEFINE_DEVICE_ADD(disk)
|
2016-05-03 09:45:05 +02:00
|
|
|
/* nic */
|
|
|
|
DEFINE_DEVICE_ADD(nic)
|
2014-05-13 19:13:17 +02:00
|
|
|
|
|
|
|
+/* vscsi */
|
2016-05-03 09:45:05 +02:00
|
|
|
+DEFINE_DEVICE_ADD(vscsictrl)
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
/* vtpm */
|
|
|
|
DEFINE_DEVICE_ADD(vtpm)
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -7309,6 +7313,11 @@ int libxl_retrieve_domain_configuration(
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
MERGE(nic, nics, COMPARE_DEVID, {});
|
|
|
|
|
|
|
|
+ MERGE(vscsictrl, vscsictrls, COMPARE_DEVID, {
|
|
|
|
+ libxl_device_vscsictrl_dispose(dst);
|
|
|
|
+ libxl_device_vscsictrl_copy(CTX, dst, src);
|
|
|
|
+ });
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
MERGE(vtpm, vtpms, COMPARE_DEVID, {});
|
|
|
|
|
|
|
|
MERGE(pci, pcidevs, COMPARE_PCI, {});
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl.h
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl.h
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl.h
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -880,6 +880,13 @@ void libxl_mac_copy(libxl_ctx *ctx, libx
|
|
|
|
#define LIBXL_HAVE_PCITOPOLOGY 1
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
/*
|
|
|
|
+ * LIBXL_HAVE_VSCSI
|
2014-05-13 19:13:17 +02:00
|
|
|
+ *
|
2016-05-03 09:45:05 +02:00
|
|
|
+ * If this is defined, the PV SCSI feature is supported.
|
2014-05-13 19:13:17 +02:00
|
|
|
+ */
|
2016-05-03 09:45:05 +02:00
|
|
|
+#define LIBXL_HAVE_VSCSI 1
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+/*
|
|
|
|
* LIBXL_HAVE_SOCKET_BITMAP
|
|
|
|
*
|
|
|
|
* If this is defined, then libxl_socket_bitmap_alloc and
|
|
|
|
@@ -1710,6 +1717,41 @@ int libxl_device_channel_getinfo(libxl_c
|
|
|
|
libxl_device_channel *channel,
|
|
|
|
libxl_channelinfo *channelinfo);
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
+/* Virtual SCSI */
|
|
|
|
+int libxl_device_vscsictrl_add(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsi,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
|
|
|
+int libxl_device_vscsictrl_remove(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsi,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
|
|
|
+int libxl_device_vscsictrl_destroy(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsi,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
|
|
|
+
|
|
|
|
+libxl_device_vscsictrl *libxl_device_vscsictrl_list(libxl_ctx *ctx, uint32_t domid, int *num);
|
|
|
|
+int libxl_device_vscsictrl_getinfo(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl_device_vscsidev *vscsidev,
|
|
|
|
+ libxl_vscsiinfo *vscsiinfo);
|
|
|
|
+int libxl_device_vscsidev_add(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsidev *dev,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
|
|
|
+/* Remove vscsidev connected to vscsictrl */
|
|
|
|
+int libxl_device_vscsidev_remove(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsidev *dev,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
|
|
|
+void libxl_device_vscsictrl_append_vscsidev(libxl_ctx *ctx,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ libxl_device_vscsidev *dev);
|
|
|
|
+void libxl_device_vscsictrl_remove_vscsidev(libxl_ctx *ctx,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ unsigned int idx);
|
|
|
|
+
|
|
|
|
/* Virtual TPMs */
|
|
|
|
int libxl_device_vtpm_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vtpm *vtpm,
|
|
|
|
const libxl_asyncop_how *ao_how)
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl_create.c
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl_create.c
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl_create.c
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -740,6 +740,8 @@ static void domcreate_bootloader_done(li
|
|
|
|
static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs,
|
|
|
|
int ret);
|
|
|
|
|
|
|
|
+static void domcreate_attach_vscsictrls(libxl__egc *egc, libxl__multidev *multidev,
|
|
|
|
+ int ret);
|
|
|
|
static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
|
|
|
|
int ret);
|
|
|
|
static void domcreate_attach_usbctrls(libxl__egc *egc,
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -1432,13 +1434,13 @@ static void domcreate_devmodel_started(l
|
2016-05-03 09:45:05 +02:00
|
|
|
if (d_config->num_nics > 0) {
|
|
|
|
/* Attach nics */
|
|
|
|
libxl__multidev_begin(ao, &dcs->multidev);
|
|
|
|
- dcs->multidev.callback = domcreate_attach_vtpms;
|
|
|
|
+ dcs->multidev.callback = domcreate_attach_vscsictrls;
|
|
|
|
libxl__add_nics(egc, ao, domid, d_config, &dcs->multidev);
|
|
|
|
libxl__multidev_prepared(egc, &dcs->multidev, 0);
|
|
|
|
return;
|
|
|
|
}
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
- domcreate_attach_vtpms(egc, &dcs->multidev, 0);
|
|
|
|
+ domcreate_attach_vscsictrls(egc, &dcs->multidev, 0);
|
2014-05-13 19:13:17 +02:00
|
|
|
return;
|
2016-05-03 09:45:05 +02:00
|
|
|
|
|
|
|
error_out:
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -1446,7 +1448,7 @@ error_out:
|
2016-05-03 09:45:05 +02:00
|
|
|
domcreate_complete(egc, dcs, ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void domcreate_attach_vtpms(libxl__egc *egc,
|
|
|
|
+static void domcreate_attach_vscsictrls(libxl__egc *egc,
|
|
|
|
libxl__multidev *multidev,
|
|
|
|
int ret)
|
|
|
|
{
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -1461,6 +1463,39 @@ static void domcreate_attach_vtpms(libxl
|
2016-05-03 09:45:05 +02:00
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ /* Plug vscsi devices */
|
|
|
|
+ if (d_config->num_vscsictrls > 0) {
|
|
|
|
+ /* Attach vscsictrls */
|
|
|
|
+ libxl__multidev_begin(ao, &dcs->multidev);
|
|
|
|
+ dcs->multidev.callback = domcreate_attach_vtpms;
|
|
|
|
+ libxl__add_vscsictrls(egc, ao, domid, d_config, &dcs->multidev);
|
|
|
|
+ libxl__multidev_prepared(egc, &dcs->multidev, 0);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ domcreate_attach_vtpms(egc, multidev, 0);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+error_out:
|
|
|
|
+ assert(ret);
|
|
|
|
+ domcreate_complete(egc, dcs, ret);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void domcreate_attach_vtpms(libxl__egc *egc,
|
|
|
|
+ libxl__multidev *multidev,
|
|
|
|
+ int ret)
|
|
|
|
+{
|
|
|
|
+ libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
|
|
|
|
+ STATE_AO_GC(dcs->ao);
|
|
|
|
+ int domid = dcs->guest_domid;
|
|
|
|
+
|
|
|
|
+ libxl_domain_config* const d_config = dcs->guest_config;
|
|
|
|
+
|
|
|
|
+ if(ret) {
|
|
|
|
+ LOG(ERROR, "unable to add vscsi devices");
|
|
|
|
+ goto error_out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
/* Plug vtpm devices */
|
|
|
|
if (d_config->num_vtpms > 0) {
|
|
|
|
/* Attach vtpms */
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl_device.c
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl_device.c
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl_device.c
|
- Add patches from proposed upstream series to load BIOS's from
the toolstack instead of embedding in hvmloader
http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01626.html
0001-libxc-Rework-extra-module-initialisation.patch,
0002-libxc-Prepare-a-start-info-structure-for-hvmloader.patch,
0003-configure-define-SEABIOS_PATH-and-OVMF_PATH.patch,
0004-firmware-makefile-install-BIOS-blob.patch,
0005-libxl-Load-guest-BIOS-from-file.patch,
0006-xen-Move-the-hvm_start_info-C-representation-from-li.patch,
0007-hvmloader-Grab-the-hvm_start_info-pointer.patch,
0008-hvmloader-Locate-the-BIOS-blob.patch,
0009-hvmloader-Check-modules-whereabouts-in-perform_tests.patch,
0010-hvmloader-Load-SeaBIOS-from-hvm_start_info-modules.patch,
0011-hvmloader-Load-OVMF-from-modules.patch,
0012-hvmloader-Specific-bios_load-function-required.patch,
0013-hvmloader-Always-build-in-SeaBIOS-and-OVMF-loader.patch,
0014-configure-do-not-depend-on-SEABIOS_PATH-or-OVMF_PATH.patch
- Enable support for UEFI on x86_64 using the ovmf-x86_64-ms.bin
firmware from qemu-ovmf-x86_64. The firmware is preloaded with
Microsoft keys to more closely resemble firmware on real hardware
FATE#320490
OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=416
2016-04-13 21:43:10 +02:00
|
|
|
@@ -616,6 +616,7 @@ void libxl__multidev_prepared(libxl__egc
|
2014-05-13 19:13:17 +02:00
|
|
|
* The following functions are defined:
|
|
|
|
* libxl__add_disks
|
|
|
|
* libxl__add_nics
|
2016-05-03 09:45:05 +02:00
|
|
|
+ * libxl__add_vscsictrls
|
2014-05-13 19:13:17 +02:00
|
|
|
* libxl__add_vtpms
|
2016-03-25 23:10:02 +01:00
|
|
|
* libxl__add_usbctrls
|
|
|
|
* libxl__add_usbs
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -637,6 +638,7 @@ void libxl__multidev_prepared(libxl__egc
|
|
|
|
|
|
|
|
DEFINE_DEVICES_ADD(disk)
|
|
|
|
DEFINE_DEVICES_ADD(nic)
|
|
|
|
+DEFINE_DEVICES_ADD(vscsictrl)
|
2014-05-13 19:13:17 +02:00
|
|
|
DEFINE_DEVICES_ADD(vtpm)
|
2016-03-25 23:10:02 +01:00
|
|
|
DEFINE_DEVICES_ADD(usbctrl)
|
|
|
|
DEFINE_DEVICES_ADD(usbdev)
|
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl_internal.h
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl_internal.h
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl_internal.h
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -2627,6 +2627,10 @@ _hidden void libxl__device_nic_add(libxl
|
|
|
|
libxl_device_nic *nic,
|
|
|
|
libxl__ao_device *aodev);
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
+_hidden void libxl__device_vscsictrl_add(libxl__egc *egc, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl__ao_device *aodev);
|
|
|
|
+
|
|
|
|
_hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
|
|
|
|
libxl_device_vtpm *vtpm,
|
|
|
|
libxl__ao_device *aodev);
|
|
|
|
@@ -3485,6 +3489,10 @@ _hidden void libxl__add_nics(libxl__egc
|
|
|
|
libxl_domain_config *d_config,
|
|
|
|
libxl__multidev *multidev);
|
2014-05-13 19:13:17 +02:00
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
+_hidden void libxl__add_vscsictrls(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
|
|
|
|
+ libxl_domain_config *d_config,
|
|
|
|
+ libxl__multidev *multidev);
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
_hidden void libxl__add_vtpms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
|
|
|
|
libxl_domain_config *d_config,
|
|
|
|
libxl__multidev *multidev);
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl_types.idl
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl_types.idl
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl_types.idl
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -698,6 +698,43 @@ libxl_device_channel = Struct("device_ch
|
2015-01-14 21:58:52 +01:00
|
|
|
])),
|
2014-05-13 19:13:17 +02:00
|
|
|
])
|
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
+libxl_vscsi_pdev_type = Enumeration("vscsi_pdev_type", [
|
|
|
|
+ (0, "INVALID"),
|
|
|
|
+ (1, "HCTL"),
|
|
|
|
+ (2, "WWN"),
|
|
|
|
+ ])
|
|
|
|
+
|
|
|
|
+libxl_vscsi_hctl = Struct("vscsi_hctl", [
|
|
|
|
+ ("hst", uint32),
|
|
|
|
+ ("chn", uint32),
|
|
|
|
+ ("tgt", uint32),
|
|
|
|
+ ("lun", uint64),
|
|
|
|
+ ])
|
|
|
|
+
|
|
|
|
+libxl_vscsi_pdev = Struct("vscsi_pdev", [
|
|
|
|
+ ("p_devname", string),
|
|
|
|
+ ("u", KeyedUnion(None, libxl_vscsi_pdev_type, "type",
|
|
|
|
+ [
|
|
|
|
+ ("invalid", None),
|
|
|
|
+ ("hctl", Struct(None, [("m", libxl_vscsi_hctl)])),
|
|
|
|
+ ("wwn", Struct(None, [("m", string)])),
|
|
|
|
+ ])),
|
|
|
|
+ ])
|
|
|
|
+
|
|
|
|
+libxl_device_vscsidev = Struct("device_vscsidev", [
|
|
|
|
+ ("vscsidev_id", libxl_devid),
|
|
|
|
+ ("pdev", libxl_vscsi_pdev),
|
|
|
|
+ ("vdev", libxl_vscsi_hctl),
|
2014-05-13 19:13:17 +02:00
|
|
|
+ ])
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+libxl_device_vscsictrl = Struct("device_vscsictrl", [
|
2014-05-13 19:13:17 +02:00
|
|
|
+ ("backend_domid", libxl_domid),
|
|
|
|
+ ("devid", libxl_devid),
|
2016-05-03 09:45:05 +02:00
|
|
|
+ ("idx", libxl_devid),
|
|
|
|
+ ("vscsidevs", Array(libxl_device_vscsidev, "num_vscsidevs")),
|
|
|
|
+ ("scsi_raw_cmds", libxl_defbool),
|
2014-05-13 19:13:17 +02:00
|
|
|
+ ])
|
|
|
|
+
|
|
|
|
libxl_domain_config = Struct("domain_config", [
|
|
|
|
("c_info", libxl_domain_create_info),
|
|
|
|
("b_info", libxl_domain_build_info),
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -709,6 +746,7 @@ libxl_domain_config = Struct("domain_con
|
2016-05-03 09:45:05 +02:00
|
|
|
("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")),
|
|
|
|
("vfbs", Array(libxl_device_vfb, "num_vfbs")),
|
|
|
|
("vkbs", Array(libxl_device_vkb, "num_vkbs")),
|
|
|
|
+ ("vscsictrls", Array(libxl_device_vscsictrl, "num_vscsictrls")),
|
|
|
|
("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
|
|
|
|
# a channel manifests as a console with a name,
|
|
|
|
# see docs/misc/channels.txt
|
2016-05-26 21:33:01 +02:00
|
|
|
@@ -746,6 +784,21 @@ libxl_nicinfo = Struct("nicinfo", [
|
2016-05-03 09:45:05 +02:00
|
|
|
("rref_rx", integer),
|
2014-05-13 19:13:17 +02:00
|
|
|
], dir=DIR_OUT)
|
|
|
|
|
|
|
|
+libxl_vscsiinfo = Struct("vscsiinfo", [
|
|
|
|
+ ("backend", string),
|
|
|
|
+ ("backend_id", uint32),
|
|
|
|
+ ("frontend", string),
|
|
|
|
+ ("frontend_id", uint32),
|
|
|
|
+ ("devid", libxl_devid),
|
2016-05-03 09:45:05 +02:00
|
|
|
+ ("pdev", libxl_vscsi_pdev),
|
|
|
|
+ ("vdev", libxl_vscsi_hctl),
|
|
|
|
+ ("idx", libxl_devid),
|
|
|
|
+ ("vscsidev_id", libxl_devid),
|
|
|
|
+ ("scsi_raw_cmds", bool),
|
|
|
|
+ ("vscsictrl_state", integer),
|
|
|
|
+ ("vscsidev_state", integer),
|
2014-05-13 19:13:17 +02:00
|
|
|
+ ], dir=DIR_OUT)
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
libxl_vtpminfo = Struct("vtpminfo", [
|
|
|
|
("backend", string),
|
|
|
|
("backend_id", uint32),
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl_types_internal.idl
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxl_types_internal.idl
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl_types_internal.idl
|
- Add patches from proposed upstream series to load BIOS's from
the toolstack instead of embedding in hvmloader
http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01626.html
0001-libxc-Rework-extra-module-initialisation.patch,
0002-libxc-Prepare-a-start-info-structure-for-hvmloader.patch,
0003-configure-define-SEABIOS_PATH-and-OVMF_PATH.patch,
0004-firmware-makefile-install-BIOS-blob.patch,
0005-libxl-Load-guest-BIOS-from-file.patch,
0006-xen-Move-the-hvm_start_info-C-representation-from-li.patch,
0007-hvmloader-Grab-the-hvm_start_info-pointer.patch,
0008-hvmloader-Locate-the-BIOS-blob.patch,
0009-hvmloader-Check-modules-whereabouts-in-perform_tests.patch,
0010-hvmloader-Load-SeaBIOS-from-hvm_start_info-modules.patch,
0011-hvmloader-Load-OVMF-from-modules.patch,
0012-hvmloader-Specific-bios_load-function-required.patch,
0013-hvmloader-Always-build-in-SeaBIOS-and-OVMF-loader.patch,
0014-configure-do-not-depend-on-SEABIOS_PATH-or-OVMF_PATH.patch
- Enable support for UEFI on x86_64 using the ovmf-x86_64-ms.bin
firmware from qemu-ovmf-x86_64. The firmware is preloaded with
Microsoft keys to more closely resemble firmware on real hardware
FATE#320490
OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=416
2016-04-13 21:43:10 +02:00
|
|
|
@@ -24,6 +24,7 @@ libxl__device_kind = Enumeration("device
|
2014-05-13 19:13:17 +02:00
|
|
|
(8, "VTPM"),
|
2016-03-25 23:10:02 +01:00
|
|
|
(9, "VUSB"),
|
- Add patches from proposed upstream series to load BIOS's from
the toolstack instead of embedding in hvmloader
http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01626.html
0001-libxc-Rework-extra-module-initialisation.patch,
0002-libxc-Prepare-a-start-info-structure-for-hvmloader.patch,
0003-configure-define-SEABIOS_PATH-and-OVMF_PATH.patch,
0004-firmware-makefile-install-BIOS-blob.patch,
0005-libxl-Load-guest-BIOS-from-file.patch,
0006-xen-Move-the-hvm_start_info-C-representation-from-li.patch,
0007-hvmloader-Grab-the-hvm_start_info-pointer.patch,
0008-hvmloader-Locate-the-BIOS-blob.patch,
0009-hvmloader-Check-modules-whereabouts-in-perform_tests.patch,
0010-hvmloader-Load-SeaBIOS-from-hvm_start_info-modules.patch,
0011-hvmloader-Load-OVMF-from-modules.patch,
0012-hvmloader-Specific-bios_load-function-required.patch,
0013-hvmloader-Always-build-in-SeaBIOS-and-OVMF-loader.patch,
0014-configure-do-not-depend-on-SEABIOS_PATH-or-OVMF_PATH.patch
- Enable support for UEFI on x86_64 using the ovmf-x86_64-ms.bin
firmware from qemu-ovmf-x86_64. The firmware is preloaded with
Microsoft keys to more closely resemble firmware on real hardware
FATE#320490
OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=416
2016-04-13 21:43:10 +02:00
|
|
|
(10, "QUSB"),
|
|
|
|
+ (11, "VSCSI"),
|
2014-05-13 19:13:17 +02:00
|
|
|
])
|
|
|
|
|
|
|
|
libxl__console_backend = Enumeration("console_backend", [
|
2016-05-03 09:45:05 +02:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxl_vscsi.c
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-05-03 09:45:05 +02:00
|
|
|
--- /dev/null
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxl_vscsi.c
|
|
|
|
@@ -0,0 +1,1169 @@
|
|
|
|
+/*
|
|
|
|
+ * Copyright (C) 2016 SUSE Linux GmbH
|
|
|
|
+ * Author Olaf Hering <olaf@aepfle.de>
|
|
|
|
+ *
|
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
|
+ * it under the terms of the GNU Lesser General Public License as published
|
|
|
|
+ * by the Free Software Foundation; version 2.1 only. with the special
|
|
|
|
+ * exception on linking described in file LICENSE.
|
|
|
|
+ *
|
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
+ * GNU Lesser General Public License for more details.
|
|
|
|
+ */
|
|
|
|
+#include "libxl_osdeps.h" /* must come before any other headers */
|
|
|
|
+#include "libxl_internal.h"
|
|
|
|
+
|
|
|
|
+typedef struct vscsidev_rm {
|
|
|
|
+ libxl_device_vscsictrl *ctrl;
|
|
|
|
+ char *be_path;
|
|
|
|
+ int dev_wait;
|
|
|
|
+ libxl__device dev;
|
|
|
|
+} vscsidev_rm_t;
|
|
|
|
+
|
|
|
|
+typedef void (*vscsictrl_add)(libxl__egc *egc,
|
|
|
|
+ libxl__ao_device *aodev,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl_domain_config *d_config);
|
|
|
|
+
|
|
|
|
+#define LIBXL_CTRL_INDEX "libxl_ctrl_index"
|
|
|
|
+
|
|
|
|
+#define XLU_WWN_LEN 16
|
|
|
|
+
|
|
|
|
+static int vscsi_parse_hctl(char *str, libxl_vscsi_hctl *hctl)
|
2014-05-13 19:13:17 +02:00
|
|
|
+{
|
2016-05-03 09:45:05 +02:00
|
|
|
+ unsigned int hst, chn, tgt;
|
|
|
|
+ unsigned long long lun;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ if (sscanf(str, "%u:%u:%u:%llu", &hst, &chn, &tgt, &lun) != 4)
|
|
|
|
+ return ERROR_INVAL;
|
|
|
|
+
|
|
|
|
+ hctl->hst = hst;
|
|
|
|
+ hctl->chn = chn;
|
|
|
|
+ hctl->tgt = tgt;
|
|
|
|
+ hctl->lun = lun;
|
|
|
|
+ return 0;
|
2014-05-13 19:13:17 +02:00
|
|
|
+}
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+/* Translate p-dev back into pdev.type */
|
|
|
|
+static bool vscsi_parse_pdev(libxl__gc *gc, libxl_device_vscsidev *dev,
|
|
|
|
+ char *c, char *p, char *v)
|
2014-05-13 19:13:17 +02:00
|
|
|
+{
|
2016-05-03 09:45:05 +02:00
|
|
|
+ libxl_vscsi_hctl hctl;
|
|
|
|
+ unsigned long long lun;
|
|
|
|
+ char wwn[XLU_WWN_LEN + 1];
|
|
|
|
+ bool parsed_ok = false;
|
|
|
|
+
|
|
|
|
+ libxl_vscsi_hctl_init(&hctl);
|
|
|
|
+
|
|
|
|
+ dev->pdev.p_devname = libxl__strdup(NOGC, c);
|
|
|
|
+
|
|
|
|
+ if (strncmp(p, "naa.", 4) == 0) {
|
|
|
|
+ /* WWN as understood by pvops */
|
|
|
|
+ memset(wwn, 0, sizeof(wwn));
|
|
|
|
+ if (sscanf(p, "naa.%16[0-9a-fA-F]:%llu", wwn, &lun) == 2) {
|
|
|
|
+ libxl_vscsi_pdev_init_type(&dev->pdev, LIBXL_VSCSI_PDEV_TYPE_WWN);
|
|
|
|
+ dev->pdev.u.wwn.m = libxl__strdup(NOGC, p);
|
|
|
|
+ parsed_ok = true;
|
|
|
|
+ }
|
|
|
|
+ } else if (vscsi_parse_hctl(p, &hctl) == 0) {
|
|
|
|
+ /* Either xenlinux, or pvops with properly configured alias in sysfs */
|
|
|
|
+ libxl_vscsi_pdev_init_type(&dev->pdev, LIBXL_VSCSI_PDEV_TYPE_HCTL);
|
|
|
|
+ libxl_vscsi_hctl_copy(CTX, &dev->pdev.u.hctl.m, &hctl);
|
|
|
|
+ parsed_ok = true;
|
|
|
|
+ }
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ if (parsed_ok && vscsi_parse_hctl(v, &dev->vdev) != 0)
|
|
|
|
+ parsed_ok = false;
|
|
|
|
+
|
|
|
|
+ libxl_vscsi_hctl_dispose(&hctl);
|
|
|
|
+
|
|
|
|
+ return parsed_ok;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool vscsi_fill_dev(libxl__gc *gc,
|
|
|
|
+ xs_transaction_t t,
|
|
|
|
+ const char *devs_path,
|
|
|
|
+ const char *dev_dir,
|
|
|
|
+ libxl_device_vscsidev *dev)
|
|
|
|
+{
|
|
|
|
+ char *path, *c, *p, *v, *s;
|
|
|
|
+ unsigned int devid;
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ r = sscanf(dev_dir, "dev-%u", &devid);
|
|
|
|
+ if (r != 1) {
|
|
|
|
+ LOG(ERROR, "expected dev-N, got '%s'", dev_dir);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ dev->vscsidev_id = devid;
|
|
|
|
+
|
|
|
|
+ path = GCSPRINTF("%s/%s", devs_path, dev_dir);
|
|
|
|
+ c = libxl__xs_read(gc, t, GCSPRINTF("%s/p-devname", path));
|
|
|
|
+ p = libxl__xs_read(gc, t, GCSPRINTF("%s/p-dev", path));
|
|
|
|
+ v = libxl__xs_read(gc, t, GCSPRINTF("%s/v-dev", path));
|
|
|
|
+ s = libxl__xs_read(gc, t, GCSPRINTF("%s/state", path));
|
|
|
|
+ LOG(DEBUG, "%s/state is %s", path, s);
|
|
|
|
+ if (!(c && p && v && s)) {
|
|
|
|
+ LOG(ERROR, "p-devname '%s' p-dev '%s' v-dev '%s'", c, p, v);
|
|
|
|
+ return false;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ if (!vscsi_parse_pdev(gc, dev, c, p, v)) {
|
|
|
|
+ LOG(ERROR, "failed to parse %s: %s %s %s %s", path, c, p, v, s);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ return true;
|
|
|
|
+}
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+static bool vscsi_fill_ctrl(libxl__gc *gc,
|
|
|
|
+ uint32_t tgt_domid,
|
|
|
|
+ xs_transaction_t t,
|
|
|
|
+ const char *fe_path,
|
|
|
|
+ const char *dir,
|
|
|
|
+ libxl_device_vscsictrl *ctrl)
|
|
|
|
+{
|
|
|
|
+ libxl_device_vscsidev dev;
|
|
|
|
+ char *tmp, *devs_path;
|
|
|
|
+ const char *be_path;
|
|
|
|
+ char **dev_dirs;
|
|
|
|
+ unsigned int ndev_dirs, dev_dir;
|
|
|
|
+ uint32_t be_domid, fe_domid;
|
|
|
|
+ char be_type[16];
|
|
|
|
+ int r;
|
|
|
|
+ bool ok;
|
|
|
|
+
|
|
|
|
+ ctrl->devid = atoi(dir);
|
|
|
|
+
|
|
|
|
+ tmp = GCSPRINTF("%s/%s/backend", fe_path, dir);
|
|
|
|
+ r = libxl__xs_read_checked(gc, t, tmp, &be_path);
|
|
|
|
+ if (r || !be_path)
|
|
|
|
+ goto out;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ r = sscanf(be_path, "/local/domain/%u/backend/%15[^/]/%u",
|
|
|
|
+ &be_domid, be_type, &fe_domid);
|
|
|
|
+ if (r != 3 || fe_domid != tgt_domid)
|
|
|
|
+ goto out;
|
|
|
|
+ ctrl->backend_domid = be_domid;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ tmp = libxl__xs_read(gc, t, GCSPRINTF("%s/" LIBXL_CTRL_INDEX, be_path));
|
|
|
|
+ if (!tmp)
|
|
|
|
+ goto out;
|
|
|
|
+ ctrl->idx = atoi(tmp);
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ tmp = libxl__xs_read(gc, t, GCSPRINTF("%s/feature-host", be_path));
|
|
|
|
+ if (!tmp)
|
|
|
|
+ goto out;
|
|
|
|
+ ok = atoi(tmp) != 0;
|
|
|
|
+ libxl_defbool_set(&ctrl->scsi_raw_cmds, ok);
|
|
|
|
+
|
|
|
|
+ ok = true;
|
|
|
|
+ devs_path = GCSPRINTF("%s/vscsi-devs", be_path);
|
|
|
|
+ dev_dirs = libxl__xs_directory(gc, t, devs_path, &ndev_dirs);
|
|
|
|
+ for (dev_dir = 0; dev_dirs && dev_dir < ndev_dirs; dev_dir++) {
|
|
|
|
+ libxl_device_vscsidev_init(&dev);
|
|
|
|
+ ok = vscsi_fill_dev(gc, t, devs_path, dev_dirs[dev_dir], &dev);
|
|
|
|
+ if (ok == true)
|
|
|
|
+ ok = ctrl->idx == dev.vdev.hst;
|
|
|
|
+ if (ok == true)
|
|
|
|
+ libxl_device_vscsictrl_append_vscsidev(CTX, ctrl, &dev);
|
|
|
|
+ libxl_device_vscsidev_dispose(&dev);
|
|
|
|
+ if (ok == false)
|
2014-05-13 19:13:17 +02:00
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ return ok;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+out:
|
|
|
|
+ libxl_defbool_set(&ctrl->scsi_raw_cmds, false);
|
|
|
|
+ return false;
|
2014-05-13 19:13:17 +02:00
|
|
|
+}
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+/* return an array of vscsictrls with num elements */
|
|
|
|
+static int vscsi_collect_ctrls(libxl__gc *gc,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl **ctrls,
|
|
|
|
+ int *num)
|
|
|
|
+{
|
|
|
|
+ xs_transaction_t t = XBT_NULL;
|
|
|
|
+ libxl_device_vscsictrl ctrl;
|
|
|
|
+ char *fe_path;
|
|
|
|
+ char **dirs;
|
|
|
|
+ unsigned int ndirs = 0, dir;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ fe_path = GCSPRINTF("%s/device/vscsi", libxl__xs_get_dompath(gc, domid));
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ *num = 0;
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_start(gc, &t);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ dirs = libxl__xs_directory(gc, t, fe_path, &ndirs);
|
|
|
|
+ /* Nothing to do */
|
|
|
|
+ if (!(dirs && ndirs))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ /* List of ctrls to be returned to the caller */
|
|
|
|
+ *ctrls = libxl__malloc(NOGC, ndirs * sizeof(**ctrls));
|
|
|
|
+
|
|
|
|
+ for (dir = 0; dir < ndirs; dir++) {
|
|
|
|
+ libxl_device_vscsictrl_init(*ctrls + dir);
|
|
|
|
+
|
|
|
|
+ libxl_device_vscsictrl_init(&ctrl);
|
|
|
|
+ if (vscsi_fill_ctrl(gc, domid, t, fe_path, dirs[dir], &ctrl)) {
|
|
|
|
+ libxl_device_vscsictrl_copy(CTX, *ctrls + *num, &ctrl);
|
|
|
|
+ (*num)++;
|
|
|
|
+ }
|
|
|
|
+ libxl_device_vscsictrl_dispose(&ctrl);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_commit(gc, &t);
|
|
|
|
+ if (!rc) break;
|
|
|
|
+
|
|
|
|
+ if (rc < 0) {
|
|
|
|
+ for (dir = 0; dir < ndirs; dir++)
|
|
|
|
+ libxl_device_vscsictrl_dispose(*ctrls + dir);
|
|
|
|
+ free(*ctrls);
|
|
|
|
+ *ctrls = NULL;
|
|
|
|
+ *num = 0;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ libxl__xs_transaction_abort(gc, &t);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Simplified variant of device_addrm_aocomplete */
|
|
|
|
+static void vscsi_aodev_complete(libxl__egc *egc, libxl__ao_device *aodev)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ libxl__ao_complete(egc, ao, aodev->rc);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int libxl__device_from_vscsictrl(libxl__gc *gc, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl__device *device)
|
|
|
|
+{
|
|
|
|
+ device->backend_devid = vscsictrl->devid;
|
|
|
|
+ device->backend_domid = vscsictrl->backend_domid;
|
|
|
|
+ device->devid = vscsictrl->devid;
|
|
|
|
+ device->domid = domid;
|
|
|
|
+ device->backend_kind = LIBXL__DEVICE_KIND_VSCSI;
|
|
|
|
+ device->kind = LIBXL__DEVICE_KIND_VSCSI;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsictrl_remove(libxl_ctx *ctx,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ const libxl_asyncop_how *ao_how,
|
|
|
|
+ int force)
|
|
|
|
+{
|
|
|
|
+ AO_CREATE(ctx, domid, ao_how);
|
|
|
|
+ libxl__device *device;
|
|
|
|
+ libxl__ao_device *aodev;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ GCNEW(device);
|
|
|
|
+ rc = libxl__device_from_vscsictrl(gc, domid, vscsictrl, device);
|
|
|
|
+ if (rc != 0) goto out;
|
|
|
|
+
|
|
|
|
+ GCNEW(aodev);
|
|
|
|
+ libxl__prepare_ao_device(ao, aodev);
|
|
|
|
+ aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
|
|
|
|
+ aodev->dev = device;
|
|
|
|
+ aodev->callback = vscsi_aodev_complete;
|
|
|
|
+ aodev->force = force;
|
|
|
|
+ libxl__initiate_device_generic_remove(egc, aodev);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ if (rc) return AO_CREATE_FAIL(rc);
|
|
|
|
+ return AO_INPROGRESS;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsidev_be_set_rm(libxl__gc *gc,
|
|
|
|
+ libxl_device_vscsidev *v,
|
|
|
|
+ flexarray_t *back)
|
|
|
|
+{
|
|
|
|
+ int rc;
|
|
|
|
+ char *dir;
|
|
|
|
+
|
|
|
|
+ dir = GCSPRINTF("vscsi-devs/dev-%u", v->vscsidev_id);
|
|
|
|
+ rc = flexarray_append_pair(back,
|
|
|
|
+ GCSPRINTF("%s/state", dir),
|
|
|
|
+ GCSPRINTF("%d", XenbusStateClosing));
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsictrl_reconfigure_rm(libxl__ao_device *aodev,
|
|
|
|
+ const char *state_path,
|
|
|
|
+ int *be_wait)
|
|
|
|
+
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ vscsidev_rm_t *vscsidev_rm = CONTAINER_OF(aodev->dev, *vscsidev_rm, dev);
|
|
|
|
+ libxl_device_vscsictrl *ctrl = vscsidev_rm->ctrl;
|
|
|
|
+ const char *be_path = vscsidev_rm->be_path;
|
|
|
|
+ int rc, i, be_state;
|
|
|
|
+ char *dev_path, *state_val;
|
|
|
|
+ flexarray_t *back;
|
|
|
|
+ libxl_device_vscsidev *v;
|
|
|
|
+ xs_transaction_t t = XBT_NULL;
|
|
|
|
+
|
|
|
|
+ /* Prealloc key+value: 1 toplevel + 1 per device */
|
|
|
|
+ i = 2 * (1 + 1);
|
|
|
|
+ back = flexarray_make(gc, i, 1);
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ rc = libxl__xs_transaction_start(gc, &t);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ state_val = libxl__xs_read(gc, t, state_path);
|
|
|
|
+ LOG(DEBUG, "%s is %s", state_path, state_val);
|
|
|
|
+ if (!state_val) {
|
|
|
|
+ rc = ERROR_NOTFOUND;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ be_state = atoi(state_val);
|
|
|
|
+ switch (be_state) {
|
|
|
|
+ case XenbusStateUnknown:
|
|
|
|
+ case XenbusStateInitialising:
|
|
|
|
+ case XenbusStateClosing:
|
|
|
|
+ case XenbusStateClosed:
|
|
|
|
+ default:
|
|
|
|
+ /* The backend is in a bad state */
|
|
|
|
+ rc = ERROR_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ case XenbusStateInitialised:
|
|
|
|
+ case XenbusStateReconfiguring:
|
|
|
|
+ case XenbusStateReconfigured:
|
|
|
|
+ /* Backend is still busy, caller has to retry */
|
|
|
|
+ rc = ERROR_NOT_READY;
|
|
|
|
+ goto out;
|
|
|
|
+ case XenbusStateInitWait:
|
|
|
|
+ /* The frontend did not connect yet */
|
|
|
|
+ *be_wait = XenbusStateInitWait;
|
|
|
|
+ vscsidev_rm->dev_wait = XenbusStateClosing;
|
|
|
|
+ break;
|
|
|
|
+ case XenbusStateConnected:
|
|
|
|
+ /* The backend can handle reconfigure */
|
|
|
|
+ *be_wait = XenbusStateConnected;
|
|
|
|
+ vscsidev_rm->dev_wait = XenbusStateClosed;
|
|
|
|
+ flexarray_append_pair(back, "state",
|
|
|
|
+ GCSPRINTF("%d", XenbusStateReconfiguring));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Append new vscsidev or skip existing */
|
|
|
|
+ for (i = 0; i < ctrl->num_vscsidevs; i++) {
|
|
|
|
+ unsigned int nb = 0;
|
|
|
|
+ v = ctrl->vscsidevs + i;
|
|
|
|
+ dev_path = GCSPRINTF("%s/vscsi-devs/dev-%u", be_path, v->vscsidev_id);
|
|
|
|
+ if (!libxl__xs_directory(gc, XBT_NULL, dev_path, &nb)) {
|
|
|
|
+ /* FIXME Sanity check */
|
|
|
|
+ LOG(DEBUG, "%s does not exist anymore", dev_path);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ rc = vscsidev_be_set_rm(gc, v, back);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ libxl__xs_writev(gc, t, be_path,
|
|
|
|
+ libxl__xs_kvs_of_flexarray(gc, back, back->count));
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_commit(gc, &t);
|
|
|
|
+ if (!rc) break;
|
|
|
|
+ if (rc < 0) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ libxl__xs_transaction_abort(gc, &t);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl_remove_be_dev(libxl__gc *gc,
|
|
|
|
+ libxl_device_vscsidev *v,
|
|
|
|
+ xs_transaction_t t,
|
|
|
|
+ const char *be_path,
|
|
|
|
+ int dev_wait)
|
|
|
|
+{
|
|
|
|
+ char *dir, *path, *val;
|
|
|
|
+
|
|
|
|
+ dir = GCSPRINTF("%s/vscsi-devs/dev-%u", be_path, v->vscsidev_id);
|
|
|
|
+ path = GCSPRINTF("%s/state", dir);
|
|
|
|
+ val = libxl__xs_read(gc, t, path);
|
|
|
|
+ LOG(DEBUG, "%s is %s", path, val);
|
|
|
|
+ if (val && strcmp(val, GCSPRINTF("%d", dev_wait)) == 0) {
|
|
|
|
+ xs_rm(CTX->xsh, t, GCSPRINTF("%s/state", dir));
|
|
|
|
+ xs_rm(CTX->xsh, t, GCSPRINTF("%s/p-devname", dir));
|
|
|
|
+ xs_rm(CTX->xsh, t, GCSPRINTF("%s/p-dev", dir));
|
|
|
|
+ xs_rm(CTX->xsh, t, GCSPRINTF("%s/v-dev", dir));
|
|
|
|
+ xs_rm(CTX->xsh, t, dir);
|
|
|
|
+ } else {
|
|
|
|
+ LOG(ERROR, "%s has %s, expected %d", path, val, dev_wait);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl_remove_be_cb(libxl__egc *egc,
|
|
|
|
+ libxl__ev_devstate *ds,
|
|
|
|
+ int rc)
|
|
|
|
+{
|
|
|
|
+ libxl__ao_device *aodev = CONTAINER_OF(ds, *aodev, backend_ds);
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ vscsidev_rm_t *vscsidev_rm = CONTAINER_OF(aodev->dev, *vscsidev_rm, dev);
|
|
|
|
+ libxl_device_vscsictrl *ctrl = vscsidev_rm->ctrl;
|
|
|
|
+ xs_transaction_t t = XBT_NULL;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ rc = libxl__xs_transaction_start(gc, &t);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ctrl->num_vscsidevs; i++)
|
|
|
|
+ vscsictrl_remove_be_dev(gc, ctrl->vscsidevs + i, t,
|
|
|
|
+ vscsidev_rm->be_path,
|
|
|
|
+ vscsidev_rm->dev_wait);
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_commit(gc, &t);
|
|
|
|
+ if (!rc) break;
|
|
|
|
+ if (rc < 0) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsidev__remove(libxl__egc *egc, libxl__ao_device *aodev)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ vscsidev_rm_t *vscsidev_rm = CONTAINER_OF(aodev->dev, *vscsidev_rm, dev);
|
|
|
|
+ char *state_path;
|
|
|
|
+ int rc, be_wait;
|
|
|
|
+
|
|
|
|
+ vscsidev_rm->be_path = libxl__device_backend_path(gc, aodev->dev);
|
|
|
|
+ state_path = GCSPRINTF("%s/state", vscsidev_rm->be_path);
|
|
|
|
+
|
|
|
|
+ rc = vscsictrl_reconfigure_rm(aodev, state_path, &be_wait);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ rc = libxl__ev_devstate_wait(ao, &aodev->backend_ds,
|
|
|
|
+ vscsictrl_remove_be_cb,
|
|
|
|
+ state_path, be_wait,
|
|
|
|
+ LIBXL_DESTROY_TIMEOUT * 1000);
|
|
|
|
+ if (rc) {
|
|
|
|
+ LOG(ERROR, "unable to wait for %s", state_path);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ /* Notify that this is done */
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsidev_remove(libxl_ctx *ctx,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+{
|
|
|
|
+ AO_CREATE(ctx, domid, ao_how);
|
|
|
|
+ libxl__ao_device *aodev;
|
|
|
|
+ vscsidev_rm_t *vscsidev_rm;
|
|
|
|
+ libxl__device *device;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ GCNEW(aodev);
|
|
|
|
+
|
|
|
|
+ GCNEW(vscsidev_rm);
|
|
|
|
+ vscsidev_rm->ctrl = vscsictrl;
|
|
|
|
+ device = &vscsidev_rm->dev;
|
|
|
|
+
|
|
|
|
+ rc = libxl__device_from_vscsictrl(gc, domid, vscsictrl, device);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ libxl__prepare_ao_device(ao, aodev);
|
|
|
|
+ aodev->dev = device;
|
|
|
|
+ aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
|
|
|
|
+ aodev->callback = vscsi_aodev_complete;
|
|
|
|
+
|
|
|
|
+ vscsidev__remove(egc, aodev);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ if (rc) AO_CREATE_FAIL(rc);
|
|
|
|
+ return AO_INPROGRESS;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsidev_backend_add(libxl__gc *gc,
|
|
|
|
+ libxl_device_vscsidev *v,
|
|
|
|
+ flexarray_t *back)
|
|
|
|
+{
|
|
|
|
+ int rc;
|
|
|
|
+ char *dir;
|
|
|
|
+ unsigned int hst, chn, tgt;
|
|
|
|
+ unsigned long long lun;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ dir = GCSPRINTF("vscsi-devs/dev-%u", v->vscsidev_id);
|
|
|
|
+ switch (v->pdev.type) {
|
|
|
|
+ case LIBXL_VSCSI_PDEV_TYPE_WWN:
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ GCSPRINTF("%s/p-dev", dir),
|
|
|
|
+ v->pdev.u.wwn.m);
|
|
|
|
+ break;
|
|
|
|
+ case LIBXL_VSCSI_PDEV_TYPE_HCTL:
|
|
|
|
+ hst = v->pdev.u.hctl.m.hst;
|
|
|
|
+ chn = v->pdev.u.hctl.m.chn;
|
|
|
|
+ tgt = v->pdev.u.hctl.m.tgt;
|
|
|
|
+ lun = v->pdev.u.hctl.m.lun;
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ GCSPRINTF("%s/p-dev", dir),
|
|
|
|
+ GCSPRINTF("%u:%u:%u:%llu", hst, chn, tgt, lun));
|
|
|
|
+ break;
|
|
|
|
+ case LIBXL_VSCSI_PDEV_TYPE_INVALID:
|
|
|
|
+ /* fallthrough */
|
|
|
|
+ default:
|
|
|
|
+ rc = ERROR_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ GCSPRINTF("%s/p-devname", dir),
|
|
|
|
+ v->pdev.p_devname);
|
|
|
|
+ hst = v->vdev.hst;
|
|
|
|
+ chn = v->vdev.chn;
|
|
|
|
+ tgt = v->vdev.tgt;
|
|
|
|
+ lun = v->vdev.lun;
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ GCSPRINTF("%s/v-dev", dir),
|
|
|
|
+ GCSPRINTF("%u:%u:%u:%llu", hst, chn, tgt, lun));
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ GCSPRINTF("%s/state", dir),
|
|
|
|
+ GCSPRINTF("%d", XenbusStateInitialising));
|
|
|
|
+ rc = 0;
|
|
|
|
+out:
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl_new_backend(libxl__egc *egc,
|
|
|
|
+ libxl__ao_device *aodev,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl_domain_config *d_config)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ int rc, i;
|
|
|
|
+ flexarray_t *back;
|
|
|
|
+ flexarray_t *front;
|
|
|
|
+ libxl_device_vscsidev *v;
|
|
|
|
+ xs_transaction_t t = XBT_NULL;
|
|
|
|
+
|
|
|
|
+ /* Prealloc key+value: 4 toplevel + 4 per device */
|
|
|
|
+ i = 2 * (4 + (4 * vscsictrl->num_vscsidevs));
|
|
|
|
+ back = flexarray_make(gc, i, 1);
|
|
|
|
+ front = flexarray_make(gc, 2 * 2, 1);
|
|
|
|
+
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ "frontend-id",
|
|
|
|
+ GCSPRINTF("%d", aodev->dev->domid));
|
|
|
|
+ flexarray_append_pair(back, "online", "1");
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ "state",
|
|
|
|
+ GCSPRINTF("%d", XenbusStateInitialising));
|
|
|
|
+ flexarray_append_pair(back,
|
|
|
|
+ LIBXL_CTRL_INDEX,
|
|
|
|
+ GCSPRINTF("%d", vscsictrl->idx));
|
|
|
|
+ flexarray_append_pair(back, "feature-host",
|
|
|
|
+ libxl_defbool_val(vscsictrl->scsi_raw_cmds) ?
|
|
|
|
+ "1" : "0");
|
|
|
|
+
|
|
|
|
+ flexarray_append_pair(front,
|
|
|
|
+ "backend-id",
|
|
|
|
+ GCSPRINTF("%d", vscsictrl->backend_domid));
|
|
|
|
+ flexarray_append_pair(front,
|
|
|
|
+ "state",
|
|
|
|
+ GCSPRINTF("%d", XenbusStateInitialising));
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < vscsictrl->num_vscsidevs; i++) {
|
|
|
|
+ v = vscsictrl->vscsidevs + i;
|
|
|
|
+ rc = vscsidev_backend_add(gc, v, back);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ rc = libxl__xs_transaction_start(gc, &t);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ rc = libxl__device_exists(gc, t, aodev->dev);
|
|
|
|
+ if (rc < 0) goto out;
|
|
|
|
+ if (rc == 1) { /* already exists in xenstore */
|
|
|
|
+ LOG(ERROR, "device already exists in xenstore");
|
|
|
|
+ rc = ERROR_DEVICE_EXISTS;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (aodev->update_json) {
|
|
|
|
+ rc = libxl__set_domain_configuration(gc, aodev->dev->domid, d_config);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ libxl__device_generic_add(gc, t, aodev->dev,
|
|
|
|
+ libxl__xs_kvs_of_flexarray(gc, back,
|
|
|
|
+ back->count),
|
|
|
|
+ libxl__xs_kvs_of_flexarray(gc, front,
|
|
|
|
+ front->count),
|
|
|
|
+ NULL);
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_commit(gc, &t);
|
|
|
|
+ if (!rc) break;
|
|
|
|
+ if (rc < 0) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ libxl__wait_device_connection(egc, aodev);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ libxl__xs_transaction_abort(gc, &t);
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl_do_reconfigure_add_cb(libxl__egc *egc,
|
|
|
|
+ libxl__ev_devstate *ds,
|
|
|
|
+ int rc)
|
|
|
|
+{
|
|
|
|
+ libxl__ao_device *aodev = CONTAINER_OF(ds, *aodev, backend_ds);
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl_do_reconfigure_add(libxl__egc *egc,
|
|
|
|
+ libxl__ao_device *aodev,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl_domain_config *d_config)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ int rc, i, be_state, be_wait;
|
|
|
|
+ const char *be_path;
|
|
|
|
+ char *dev_path, *state_path, *state_val;
|
|
|
|
+ flexarray_t *back;
|
|
|
|
+ libxl_device_vscsidev *v;
|
|
|
|
+ xs_transaction_t t = XBT_NULL;
|
|
|
|
+ bool do_reconfigure = false;
|
|
|
|
+
|
|
|
|
+ /* Prealloc key+value: 1 toplevel + 4 per device */
|
|
|
|
+ i = 2 * (1 + (4 * vscsictrl->num_vscsidevs));
|
|
|
|
+ back = flexarray_make(gc, i, 1);
|
|
|
|
+
|
|
|
|
+ be_path = libxl__device_backend_path(gc, aodev->dev);
|
|
|
|
+ state_path = GCSPRINTF("%s/state", be_path);
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ rc = libxl__xs_transaction_start(gc, &t);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ state_val = libxl__xs_read(gc, t, state_path);
|
|
|
|
+ LOG(DEBUG, "%s is %s", state_path, state_val);
|
|
|
|
+ if (!state_val) {
|
|
|
|
+ rc = ERROR_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ be_state = atoi(state_val);
|
|
|
|
+ switch (be_state) {
|
|
|
|
+ case XenbusStateUnknown:
|
|
|
|
+ case XenbusStateInitialising:
|
|
|
|
+ case XenbusStateClosing:
|
|
|
|
+ case XenbusStateClosed:
|
|
|
|
+ default:
|
|
|
|
+ /* The backend is in a bad state */
|
|
|
|
+ rc = ERROR_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ case XenbusStateInitialised:
|
|
|
|
+ case XenbusStateReconfiguring:
|
|
|
|
+ case XenbusStateReconfigured:
|
|
|
|
+ /* Backend is still busy, caller has to retry */
|
|
|
|
+ rc = ERROR_NOT_READY;
|
|
|
|
+ goto out;
|
|
|
|
+ case XenbusStateInitWait:
|
|
|
|
+ /* The frontend did not connect yet */
|
|
|
|
+ be_wait = XenbusStateInitWait;
|
|
|
|
+ do_reconfigure = false;
|
|
|
|
+ break;
|
|
|
|
+ case XenbusStateConnected:
|
|
|
|
+ /* The backend can handle reconfigure */
|
|
|
|
+ be_wait = XenbusStateConnected;
|
|
|
|
+ flexarray_append_pair(back, "state", GCSPRINTF("%d", XenbusStateReconfiguring));
|
|
|
|
+ do_reconfigure = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Append new vscsidev or skip existing */
|
|
|
|
+ for (i = 0; i < vscsictrl->num_vscsidevs; i++) {
|
|
|
|
+ unsigned int nb = 0;
|
|
|
|
+ v = vscsictrl->vscsidevs + i;
|
|
|
|
+ dev_path = GCSPRINTF("%s/vscsi-devs/dev-%u", be_path, v->vscsidev_id);
|
|
|
|
+ if (libxl__xs_directory(gc, XBT_NULL, dev_path, &nb)) {
|
|
|
|
+ /* FIXME Sanity check */
|
|
|
|
+ LOG(DEBUG, "%s exists already with %u entries", dev_path, nb);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ rc = vscsidev_backend_add(gc, v, back);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (aodev->update_json) {
|
|
|
|
+ rc = libxl__set_domain_configuration(gc, aodev->dev->domid, d_config);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ libxl__xs_writev(gc, t, be_path,
|
|
|
|
+ libxl__xs_kvs_of_flexarray(gc, back, back->count));
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_commit(gc, &t);
|
|
|
|
+ if (!rc) break;
|
|
|
|
+ if (rc < 0) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (do_reconfigure) {
|
|
|
|
+ rc = libxl__ev_devstate_wait(ao, &aodev->backend_ds,
|
|
|
|
+ vscsictrl_do_reconfigure_add_cb,
|
|
|
|
+ state_path, be_wait,
|
|
|
|
+ LIBXL_INIT_TIMEOUT * 1000);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ libxl__xs_transaction_abort(gc, &t);
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsictrl_next_vscsidev_id(libxl__gc *gc,
|
|
|
|
+ const char *libxl_path,
|
|
|
|
+ libxl_devid *vscsidev_id)
|
|
|
|
+{
|
|
|
|
+ const char *val;
|
|
|
|
+ xs_transaction_t t = XBT_NULL;
|
|
|
|
+ unsigned int id;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ rc = libxl__xs_transaction_start(gc, &t);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ val = libxl__xs_read(gc, t, libxl_path);
|
|
|
|
+ id = val ? strtoul(val, NULL, 10) : 0;
|
|
|
|
+
|
|
|
|
+ LOG(DEBUG, "%s = %s vscsidev_id %u", libxl_path, val, id);
|
|
|
|
+
|
|
|
|
+ val = GCSPRINTF("%u", id + 1);
|
|
|
|
+ rc = libxl__xs_write_checked(gc, t, libxl_path, val);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ rc = libxl__xs_transaction_commit(gc, &t);
|
|
|
|
+ if (!rc) break;
|
|
|
|
+ if (rc < 0) goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *vscsidev_id = id;
|
|
|
|
+ rc = 0;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ libxl__xs_transaction_abort(gc, &t);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsictrl_assign_vscsidev_ids(libxl__gc *gc,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl)
|
|
|
|
+{
|
|
|
|
+ libxl_device_vscsidev *dev;
|
|
|
|
+ libxl_devid vscsidev_id;
|
|
|
|
+ const char *libxl_path;
|
|
|
|
+ int rc, i;
|
|
|
|
+
|
|
|
|
+ libxl_path = GCSPRINTF("%s/vscsi/%u/next_vscsidev_id",
|
|
|
|
+ libxl__xs_libxl_path(gc, domid),
|
|
|
|
+ vscsictrl->devid);
|
|
|
|
+ for (i = 0; i < vscsictrl->num_vscsidevs; i++) {
|
|
|
|
+ dev = &vscsictrl->vscsidevs[i];
|
|
|
|
+ if (dev->vscsidev_id >= 0)
|
|
|
|
+ continue;
|
|
|
|
+ rc = vscsictrl_next_vscsidev_id(gc, libxl_path, &vscsidev_id);
|
|
|
|
+ if (rc) {
|
|
|
|
+ LOG(ERROR, "failed to assign vscsidev_id to %s for %s",
|
|
|
|
+ libxl_path, dev->pdev.p_devname);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ dev->vscsidev_id = vscsidev_id;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+out:
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl_update_json(libxl__egc *egc,
|
|
|
|
+ libxl__ao_device *aodev,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ vscsictrl_add fn)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ int rc;
|
|
|
|
+ uint32_t domid = aodev->dev->domid;
|
|
|
|
+ libxl_device_vscsictrl vscsictrl_saved;
|
|
|
|
+ libxl_domain_config d_config;
|
|
|
|
+ libxl__domain_userdata_lock *lock = NULL;
|
|
|
|
+
|
|
|
|
+ libxl_domain_config_init(&d_config);
|
|
|
|
+ libxl_device_vscsictrl_init(&vscsictrl_saved);
|
|
|
|
+
|
|
|
|
+ libxl_device_vscsictrl_copy(CTX, &vscsictrl_saved, vscsictrl);
|
|
|
|
+
|
|
|
|
+ rc = vscsictrl_assign_vscsidev_ids(gc, domid, &vscsictrl_saved);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ if (aodev->update_json) {
|
|
|
|
+ lock = libxl__lock_domain_userdata(gc, domid);
|
|
|
|
+ if (!lock) {
|
|
|
|
+ rc = ERROR_LOCK_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ /* Replace or append the copy to the domain config */
|
|
|
|
+ DEVICE_ADD(vscsictrl, vscsictrls, domid, &vscsictrl_saved, COMPARE_DEVID, &d_config);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn(egc, aodev, &vscsictrl_saved, &d_config);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ if (lock) libxl__unlock_domain_userdata(lock);
|
|
|
|
+ libxl_device_vscsictrl_dispose(&vscsictrl_saved);
|
|
|
|
+ libxl_domain_config_dispose(&d_config);
|
|
|
|
+ if (rc) {
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vscsictrl__reconfigure_add(libxl__egc *egc,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl__ao_device *aodev)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ libxl__device *device;
|
|
|
|
+ vscsictrl_add fn;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ GCNEW(device);
|
|
|
|
+ rc = libxl__device_from_vscsictrl(gc, domid, vscsictrl, device);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ aodev->dev = device;
|
|
|
|
+
|
|
|
|
+ fn = vscsictrl_do_reconfigure_add;
|
|
|
|
+ vscsictrl_update_json(egc, aodev, vscsictrl, fn);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vscsictrl_reconfigure_add(libxl_ctx *ctx,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+{
|
|
|
|
+ AO_CREATE(ctx, domid, ao_how);
|
|
|
|
+ libxl__ao_device *aodev;
|
|
|
|
+
|
|
|
|
+ GCNEW(aodev);
|
|
|
|
+ libxl__prepare_ao_device(ao, aodev);
|
|
|
|
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
|
|
|
|
+ aodev->callback = vscsi_aodev_complete;
|
|
|
|
+ aodev->update_json = true;
|
|
|
|
+ vscsictrl__reconfigure_add(egc, domid, vscsictrl, aodev);
|
|
|
|
+
|
|
|
|
+ return AO_INPROGRESS;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void libxl__device_vscsictrl_add(libxl__egc *egc, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl__ao_device *aodev)
|
|
|
|
+{
|
|
|
|
+ STATE_AO_GC(aodev->ao);
|
|
|
|
+ libxl__device *device;
|
|
|
|
+ vscsictrl_add fn;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ if (vscsictrl->devid == -1) {
|
|
|
|
+ if ((vscsictrl->devid = libxl__device_nextid(gc, domid, "vscsi")) < 0) {
|
|
|
|
+ rc = ERROR_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ GCNEW(device);
|
|
|
|
+ rc = libxl__device_from_vscsictrl(gc, domid, vscsictrl, device);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+ aodev->dev = device;
|
|
|
|
+
|
|
|
|
+ fn = vscsictrl_new_backend;
|
|
|
|
+ vscsictrl_update_json(egc, aodev, vscsictrl, fn);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ aodev->rc = rc;
|
|
|
|
+ aodev->callback(egc, aodev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int libxl_device_vscsictrl_remove(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+{
|
|
|
|
+ return vscsictrl_remove(ctx, domid, vscsictrl, ao_how, 0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int libxl_device_vscsictrl_destroy(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+{
|
|
|
|
+ return vscsictrl_remove(ctx, domid, vscsictrl, ao_how, 1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+libxl_device_vscsictrl *libxl_device_vscsictrl_list(libxl_ctx *ctx,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ int *num)
|
|
|
|
+{
|
|
|
|
+ GC_INIT(ctx);
|
|
|
|
+ libxl_device_vscsictrl *ctrls = NULL;
|
|
|
|
+ int rc, num_ctrls = 0;
|
|
|
|
+
|
|
|
|
+ *num = 0;
|
|
|
|
+
|
|
|
|
+ rc = vscsi_collect_ctrls(gc, domid, &ctrls, &num_ctrls);
|
|
|
|
+ if (rc == 0)
|
|
|
|
+ *num = num_ctrls;
|
|
|
|
+
|
|
|
|
+ GC_FREE;
|
|
|
|
+ return ctrls;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int libxl_device_vscsictrl_getinfo(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsictrl *vscsictrl,
|
|
|
|
+ libxl_device_vscsidev *vscsidev,
|
|
|
|
+ libxl_vscsiinfo *vscsiinfo)
|
|
|
|
+{
|
|
|
|
+ GC_INIT(ctx);
|
|
|
|
+ char *dompath, *vscsipath;
|
|
|
|
+ char *val;
|
|
|
|
+ int rc = ERROR_FAIL;
|
|
|
|
+
|
|
|
|
+ libxl_vscsiinfo_init(vscsiinfo);
|
|
|
|
+ dompath = libxl__xs_get_dompath(gc, domid);
|
|
|
|
+ vscsiinfo->devid = vscsictrl->devid;
|
|
|
|
+ vscsiinfo->vscsidev_id = vscsidev->vscsidev_id;
|
|
|
|
+ libxl_vscsi_pdev_copy(ctx, &vscsiinfo->pdev, &vscsidev->pdev);
|
|
|
|
+ libxl_vscsi_hctl_copy(ctx, &vscsiinfo->vdev, &vscsidev->vdev);
|
|
|
|
+
|
|
|
|
+ vscsipath = GCSPRINTF("%s/device/vscsi/%d", dompath, vscsiinfo->devid);
|
|
|
|
+ vscsiinfo->backend = xs_read(ctx->xsh, XBT_NULL,
|
|
|
|
+ GCSPRINTF("%s/backend", vscsipath), NULL);
|
|
|
|
+ if (!vscsiinfo->backend)
|
|
|
|
+ goto out;
|
|
|
|
+ if(!libxl__xs_read(gc, XBT_NULL, vscsiinfo->backend))
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", vscsipath));
|
|
|
|
+ vscsiinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
|
|
|
|
+
|
|
|
|
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", vscsipath));
|
|
|
|
+ vscsiinfo->vscsictrl_state = val ? strtoul(val, NULL, 10) : -1;
|
|
|
|
+
|
|
|
|
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/" LIBXL_CTRL_INDEX, vscsipath));
|
|
|
|
+ vscsiinfo->idx = val ? strtoul(val, NULL, 10) : -1;
|
|
|
|
+
|
|
|
|
+ vscsiinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
|
|
|
|
+ GCSPRINTF("%s/frontend", vscsiinfo->backend), NULL);
|
|
|
|
+
|
|
|
|
+ val = libxl__xs_read(gc, XBT_NULL,
|
|
|
|
+ GCSPRINTF("%s/frontend-id", vscsiinfo->backend));
|
|
|
|
+ vscsiinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
|
|
|
|
+
|
|
|
|
+ val = libxl__xs_read(gc, XBT_NULL,
|
|
|
|
+ GCSPRINTF("%s/vscsi-devs/dev-%u/state",
|
|
|
|
+ vscsiinfo->backend, vscsidev->vscsidev_id));
|
|
|
|
+ vscsiinfo->vscsidev_state = val ? strtoul(val, NULL, 10) : -1;
|
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+out:
|
|
|
|
+ GC_FREE;
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int libxl_device_vscsidev_add(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsidev *vscsidev,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+{
|
|
|
|
+ GC_INIT(ctx);
|
|
|
|
+ libxl_device_vscsictrl *vc, *ctrls = NULL;
|
|
|
|
+ libxl_device_vscsidev *vd;
|
|
|
|
+ int c, d, rc, num_ctrls = 0;
|
|
|
|
+ int duplicate = 0;
|
|
|
|
+
|
|
|
|
+ rc = vscsi_collect_ctrls(gc, domid, &ctrls, &num_ctrls);
|
|
|
|
+ if (rc != 0) goto out;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for (c = 0; c < num_ctrls; ++c) {
|
|
|
|
+ vc = ctrls + c;
|
|
|
|
+ if (vc->idx != vscsidev->vdev.hst)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ for (d = 0; d < vc->num_vscsidevs; d++) {
|
|
|
|
+ vd = vc->vscsidevs + d;
|
|
|
|
+ if (vd->vdev.hst == vscsidev->vdev.hst &&
|
|
|
|
+ vd->vdev.chn == vscsidev->vdev.chn &&
|
|
|
|
+ vd->vdev.tgt == vscsidev->vdev.tgt &&
|
|
|
|
+ vd->vdev.lun == vscsidev->vdev.lun) {
|
|
|
|
+ unsigned long long lun = vd->vdev.lun;
|
|
|
|
+ LOG(ERROR, "vdev '%u:%u:%u:%llu' is already used.\n",
|
|
|
|
+ vd->vdev.hst, vd->vdev.chn, vd->vdev.tgt, lun);
|
|
|
|
+ rc = ERROR_DEVICE_EXISTS;
|
|
|
|
+ duplicate = 1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!duplicate) {
|
|
|
|
+ /* Append vscsidev to this vscsictrl, trigger reconfigure */
|
|
|
|
+ libxl_device_vscsictrl_append_vscsidev(ctx, vc, vscsidev);
|
|
|
|
+ rc = vscsictrl_reconfigure_add(ctx, domid, vc, ao_how);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (c = 0; c < num_ctrls; ++c)
|
|
|
|
+ libxl_device_vscsictrl_dispose(ctrls + c);
|
|
|
|
+ free(ctrls);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ GC_FREE;
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int libxl_device_vscsidev_remove(libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ libxl_device_vscsidev *vscsidev,
|
|
|
|
+ const libxl_asyncop_how *ao_how)
|
|
|
|
+{
|
|
|
|
+ GC_INIT(ctx);
|
|
|
|
+ libxl_device_vscsictrl *vc, *ctrls = NULL;
|
|
|
|
+ libxl_device_vscsidev *vd;
|
|
|
|
+ int c, d, rc, num_ctrls = 0;
|
|
|
|
+ int found = 0, idx;
|
|
|
|
+ int head, tail, i;
|
|
|
|
+
|
|
|
|
+ rc = vscsi_collect_ctrls(gc, domid, &ctrls, &num_ctrls);
|
|
|
|
+ if (rc != 0) goto out;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for (c = 0; c < num_ctrls; ++c) {
|
|
|
|
+ vc = ctrls + c;
|
|
|
|
+
|
|
|
|
+ for (d = 0; d < vc->num_vscsidevs; d++) {
|
|
|
|
+ vd = vc->vscsidevs + d;
|
|
|
|
+ if (vd->vdev.hst == vscsidev->vdev.hst &&
|
|
|
|
+ vd->vdev.chn == vscsidev->vdev.chn &&
|
|
|
|
+ vd->vdev.tgt == vscsidev->vdev.tgt &&
|
|
|
|
+ vd->vdev.lun == vscsidev->vdev.lun) {
|
|
|
|
+ found = 1;
|
|
|
|
+ idx = d;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (found) {
|
|
|
|
+ if (vc->num_vscsidevs > 1) {
|
|
|
|
+ /* Prepare vscsictrl, leave only desired vscsidev */
|
|
|
|
+ head = idx;
|
|
|
|
+ tail = vc->num_vscsidevs - idx - 1;
|
|
|
|
+ for (i = 0; i < head; i++)
|
|
|
|
+ libxl_device_vscsictrl_remove_vscsidev(ctx, vc, 0);
|
|
|
|
+ for (i = 0; i < tail; i++)
|
|
|
|
+ libxl_device_vscsictrl_remove_vscsidev(ctx, vc, 1);
|
|
|
|
+
|
|
|
|
+ /* Remove single vscsidev connected to this vscsictrl */
|
|
|
|
+ rc = vscsidev_remove(ctx, domid, vc, ao_how);
|
|
|
|
+ } else {
|
|
|
|
+ /* Wipe entire vscsictrl */;
|
|
|
|
+ rc = vscsictrl_remove(ctx, domid, vc, ao_how, 0);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (c = 0; c < num_ctrls; ++c)
|
|
|
|
+ libxl_device_vscsictrl_dispose(ctrls + c);
|
|
|
|
+ free(ctrls);
|
|
|
|
+
|
|
|
|
+ if (!found)
|
|
|
|
+ rc = ERROR_NOTFOUND;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ GC_FREE;
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void libxl_device_vscsictrl_append_vscsidev(libxl_ctx *ctx,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ libxl_device_vscsidev *dev)
|
|
|
|
+{
|
|
|
|
+ GC_INIT(ctx);
|
|
|
|
+ ctrl->vscsidevs = libxl__realloc(NOGC, ctrl->vscsidevs, sizeof(*dev) * (ctrl->num_vscsidevs + 1));
|
|
|
|
+ libxl_device_vscsidev_init(ctrl->vscsidevs + ctrl->num_vscsidevs);
|
|
|
|
+ libxl_device_vscsidev_copy(CTX, ctrl->vscsidevs + ctrl->num_vscsidevs, dev);
|
|
|
|
+ ctrl->num_vscsidevs++;
|
|
|
|
+ GC_FREE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void libxl_device_vscsictrl_remove_vscsidev(libxl_ctx *ctx,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ unsigned int idx)
|
|
|
|
+{
|
|
|
|
+ GC_INIT(ctx);
|
|
|
|
+ if (idx >= ctrl->num_vscsidevs)
|
|
|
|
+ return;
|
|
|
|
+ libxl_device_vscsidev_dispose(&ctrl->vscsidevs[idx]);
|
|
|
|
+ if (ctrl->num_vscsidevs > idx + 1)
|
|
|
|
+ memmove(&ctrl->vscsidevs[idx],
|
|
|
|
+ &ctrl->vscsidevs[idx + 1],
|
|
|
|
+ (ctrl->num_vscsidevs - idx - 1) * sizeof(*ctrl->vscsidevs));
|
|
|
|
+ ctrl->vscsidevs = libxl__realloc(NOGC, ctrl->vscsidevs, sizeof(*ctrl->vscsidevs) * (ctrl->num_vscsidevs - 1));
|
|
|
|
+ ctrl->num_vscsidevs--;
|
|
|
|
+ GC_FREE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Local variables:
|
|
|
|
+ * mode: C
|
|
|
|
+ * c-basic-offset: 4
|
|
|
|
+ * indent-tabs-mode: nil
|
|
|
|
+ * End:
|
|
|
|
+ */
|
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxlu_vscsi.c
|
|
|
|
===================================================================
|
|
|
|
--- /dev/null
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxlu_vscsi.c
|
|
|
|
@@ -0,0 +1,667 @@
|
|
|
|
+/*
|
|
|
|
+ * libxlu_vscsi.c - xl configuration file parsing: setup and helper functions
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2016 SUSE Linux GmbH
|
|
|
|
+ * Author Olaf Hering <olaf@aepfle.de>
|
|
|
|
+ * Author Ondřej Holeček <aaannz@gmail.com>
|
|
|
|
+ *
|
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
|
+ * it under the terms of the GNU Lesser General Public License as published
|
|
|
|
+ * by the Free Software Foundation; version 2.1 only. with the special
|
|
|
|
+ * exception on linking described in file LICENSE.
|
|
|
|
+ *
|
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
+ * GNU Lesser General Public License for more details.
|
|
|
|
+ */
|
|
|
|
+#include "libxl_osdeps.h" /* must come before any other headers */
|
|
|
|
+#include <unistd.h>
|
|
|
|
+#include <ctype.h>
|
|
|
|
+#include <dirent.h>
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
+#include <fcntl.h>
|
|
|
|
+#include "libxlu_internal.h"
|
|
|
|
+
|
|
|
|
+#ifdef __linux__
|
|
|
|
+#define LOG(_c, _x, _a...) \
|
|
|
|
+ if((_c) && (_c)->report) fprintf((_c)->report, "%s(%u): " _x "\n", __func__, __LINE__, ##_a)
|
|
|
|
+
|
|
|
|
+#define XLU_SYSFS_TARGET_PVSCSI "/sys/kernel/config/target/xen-pvscsi"
|
|
|
|
+#define XLU_WWN_LEN 16
|
|
|
|
+struct xlu__vscsi_target {
|
|
|
|
+ XLU_Config *cfg;
|
|
|
|
+ libxl_vscsi_hctl *pdev_hctl;
|
|
|
|
+ libxl_vscsi_pdev *pdev;
|
|
|
|
+ char path[PATH_MAX];
|
|
|
|
+ char udev_path[PATH_MAX];
|
|
|
|
+ char wwn[XLU_WWN_LEN + 1];
|
|
|
|
+ unsigned long long lun;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int xlu__vscsi_parse_hctl(char *str, libxl_vscsi_hctl *hctl)
|
|
|
|
+{
|
|
|
|
+ unsigned int hst, chn, tgt;
|
|
|
|
+ unsigned long long lun;
|
|
|
|
+
|
|
|
|
+ if (sscanf(str, "%u:%u:%u:%llu", &hst, &chn, &tgt, &lun) != 4)
|
|
|
|
+ return ERROR_INVAL;
|
|
|
|
+
|
|
|
|
+ hctl->hst = hst;
|
|
|
|
+ hctl->chn = chn;
|
|
|
|
+ hctl->tgt = tgt;
|
|
|
|
+ hctl->lun = lun;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static char *xlu__vscsi_trim_string(char *s)
|
|
|
|
+{
|
|
|
|
+ size_t len;
|
|
|
|
+
|
|
|
|
+ while (isspace(*s))
|
|
|
|
+ s++;
|
|
|
|
+ len = strlen(s);
|
|
|
|
+ while (len-- > 1 && isspace(s[len]))
|
|
|
|
+ s[len] = '\0';
|
|
|
|
+ return s;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int xlu__vscsi_parse_dev(XLU_Config *cfg, char *pdev, libxl_vscsi_hctl *hctl)
|
|
|
|
+{
|
|
|
|
+ struct stat dentry;
|
|
|
|
+ char *sysfs = NULL;
|
|
|
|
+ const char *type;
|
|
|
|
+ int rc, found = 0;
|
|
|
|
+ DIR *dirp;
|
|
|
|
+ struct dirent *de;
|
|
|
|
+
|
|
|
|
+ /* stat pdev to get device's sysfs entry */
|
|
|
|
+ if (stat (pdev, &dentry) < 0) {
|
|
|
|
+ LOG(cfg, "%s, device node not found", pdev);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (S_ISBLK (dentry.st_mode)) {
|
|
|
|
+ type = "block";
|
|
|
|
+ } else if (S_ISCHR (dentry.st_mode)) {
|
|
|
|
+ type = "char";
|
|
|
|
+ } else {
|
|
|
|
+ LOG(cfg, "%s, device node not a block or char device", pdev);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* /sys/dev/type/major:minor symlink added in 2.6.27 */
|
|
|
|
+ if (asprintf(&sysfs, "/sys/dev/%s/%u:%u/device/scsi_device", type,
|
|
|
|
+ major(dentry.st_rdev), minor(dentry.st_rdev)) < 0) {
|
|
|
|
+ sysfs = NULL;
|
|
|
|
+ rc = ERROR_NOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dirp = opendir(sysfs);
|
|
|
|
+ if (!dirp) {
|
|
|
|
+ LOG(cfg, "%s, no major:minor link in sysfs", pdev);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ while ((de = readdir(dirp))) {
|
|
|
|
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (xlu__vscsi_parse_hctl(de->d_name, hctl))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ found = 1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ closedir(dirp);
|
|
|
|
+
|
|
|
|
+ if (!found) {
|
|
|
|
+ LOG(cfg, "%s, no h:c:t:l link in sysfs", pdev);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+out:
|
|
|
|
+ free(sysfs);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool xlu__vscsi_compare_hctl(libxl_vscsi_hctl *a, libxl_vscsi_hctl *b)
|
|
|
|
+{
|
|
|
|
+ if (a->hst == b->hst &&
|
|
|
|
+ a->chn == b->chn &&
|
|
|
|
+ a->tgt == b->tgt &&
|
|
|
|
+ a->lun == b->lun)
|
|
|
|
+ return true;
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Finally at
|
|
|
|
+ * /sys/kernel/config/target/xen-pvscsi/naa.<wwn>/tpgt_1/lun/lun_0/<X>/udev_path
|
|
|
|
+ */
|
|
|
|
+static bool xlu__vscsi_compare_udev(struct xlu__vscsi_target *tgt)
|
|
|
|
+{
|
|
|
|
+ bool ret;
|
|
|
|
+ int fd;
|
|
|
|
+ ssize_t read_sz;
|
|
|
|
+ libxl_vscsi_hctl udev_hctl;
|
|
|
|
+
|
|
|
|
+ libxl_vscsi_hctl_init(&udev_hctl);
|
|
|
|
+
|
|
|
|
+ fd = open(tgt->path, O_RDONLY);
|
|
|
|
+ if (fd < 0){
|
|
|
|
+ ret = false;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ read_sz = read(fd, &tgt->udev_path, sizeof(tgt->udev_path) - 1);
|
|
|
|
+ close(fd);
|
|
|
|
+
|
|
|
|
+ if (read_sz <= 0 || read_sz > sizeof(tgt->udev_path) - 1) {
|
|
|
|
+ ret = false;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ tgt->udev_path[read_sz] = '\0';
|
|
|
|
+ read_sz--;
|
|
|
|
+ if (tgt->udev_path[read_sz] == '\n')
|
|
|
|
+ tgt->udev_path[read_sz] = '\0';
|
|
|
|
+
|
|
|
|
+ if (xlu__vscsi_parse_dev(tgt->cfg, tgt->udev_path, &udev_hctl)) {
|
|
|
|
+ ret = false;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ ret = xlu__vscsi_compare_hctl(tgt->pdev_hctl, &udev_hctl);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ libxl_vscsi_hctl_dispose(&udev_hctl);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* /sys/kernel/config/target/xen-pvscsi/naa.<wwn>/tpgt_1/lun/lun_0/<X>/udev_path */
|
|
|
|
+static bool xlu__vscsi_walk_dir_lun(struct xlu__vscsi_target *tgt)
|
|
|
|
+{
|
|
|
|
+ bool found;
|
|
|
|
+ DIR *dirp;
|
|
|
|
+ struct dirent *de;
|
|
|
|
+ size_t path_len = strlen(tgt->path);
|
|
|
|
+ char *subdir = &tgt->path[path_len];
|
|
|
|
+
|
|
|
|
+ dirp = opendir(tgt->path);
|
|
|
|
+ if (!dirp)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ found = false;
|
|
|
|
+ while ((de = readdir(dirp))) {
|
|
|
|
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ snprintf(subdir, sizeof(tgt->path) - path_len, "/%s/udev_path", de->d_name);
|
|
|
|
+
|
|
|
|
+ found = xlu__vscsi_compare_udev(tgt);
|
|
|
|
+ if (found)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ *subdir = '\0';
|
|
|
|
+ }
|
|
|
|
+ closedir(dirp);
|
|
|
|
+ return found;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* /sys/kernel/config/target/xen-pvscsi/naa.<wwn>/tpgt_1/lun/lun_0 */
|
|
|
|
+static bool xlu__vscsi_walk_dir_luns(struct xlu__vscsi_target *tgt)
|
|
|
|
+{
|
|
|
|
+ bool found;
|
|
|
|
+ DIR *dirp;
|
|
|
|
+ struct dirent *de;
|
|
|
|
+ size_t path_len = strlen(tgt->path);
|
|
|
|
+ char *subdir = &tgt->path[path_len];
|
|
|
|
+
|
|
|
|
+ dirp = opendir(tgt->path);
|
|
|
|
+ if (!dirp)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ found = false;
|
|
|
|
+ while ((de = readdir(dirp))) {
|
|
|
|
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (sscanf(de->d_name, "lun_%llu", &tgt->lun) != 1)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ snprintf(subdir, sizeof(tgt->path) - path_len, "/%s", de->d_name);
|
|
|
|
+
|
|
|
|
+ found = xlu__vscsi_walk_dir_lun(tgt);
|
|
|
|
+ if (found)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ *subdir = '\0';
|
|
|
|
+ }
|
|
|
|
+ closedir(dirp);
|
|
|
|
+ return found;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* /sys/kernel/config/target/xen-pvscsi/naa.<wwn>/tpgt_1 */
|
|
|
|
+static bool xlu__vscsi_walk_dir_naa(struct xlu__vscsi_target *tgt)
|
|
|
|
+{
|
|
|
|
+ bool found;
|
|
|
|
+ DIR *dirp;
|
|
|
|
+ struct dirent *de;
|
|
|
|
+ size_t path_len = strlen(tgt->path);
|
|
|
|
+ char *subdir = &tgt->path[path_len];
|
|
|
|
+ unsigned int tpgt;
|
|
|
|
+
|
|
|
|
+ dirp = opendir(tgt->path);
|
|
|
|
+ if (!dirp)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ found = false;
|
|
|
|
+ while ((de = readdir(dirp))) {
|
|
|
|
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (sscanf(de->d_name, "tpgt_%u", &tpgt) != 1)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ snprintf(subdir, sizeof(tgt->path) - path_len, "/%s/lun", de->d_name);
|
|
|
|
+
|
|
|
|
+ found = xlu__vscsi_walk_dir_luns(tgt);
|
|
|
|
+ if (found)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ *subdir = '\0';
|
|
|
|
+ }
|
|
|
|
+ closedir(dirp);
|
|
|
|
+ return found;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* /sys/kernel/config/target/xen-pvscsi/naa.<wwn> */
|
|
|
|
+static bool xlu__vscsi_find_target_wwn(struct xlu__vscsi_target *tgt)
|
|
|
|
+{
|
|
|
|
+ bool found;
|
|
|
|
+ DIR *dirp;
|
|
|
|
+ struct dirent *de;
|
|
|
|
+ size_t path_len = strlen(tgt->path);
|
|
|
|
+ char *subdir = &tgt->path[path_len];
|
|
|
|
+
|
|
|
|
+ dirp = opendir(tgt->path);
|
|
|
|
+ if (!dirp)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ found = false;
|
|
|
|
+ while ((de = readdir(dirp))) {
|
|
|
|
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (sscanf(de->d_name, "naa.%16[0-9a-fA-F]", tgt->wwn) != 1)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ snprintf(subdir, sizeof(tgt->path) - path_len, "/%s", de->d_name);
|
|
|
|
+
|
|
|
|
+ found = xlu__vscsi_walk_dir_naa(tgt);
|
|
|
|
+ if (found)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ *subdir = '\0';
|
|
|
|
+ }
|
|
|
|
+ closedir(dirp);
|
|
|
|
+ return found;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Convert pdev from config string into pdev property for backend,
|
|
|
|
+ * which is either h:c:t:l for xenlinux or naa.wwn:lun for pvops
|
|
|
|
+ */
|
|
|
|
+static int xlu__vscsi_dev_to_pdev(XLU_Config *cfg, libxl_ctx *ctx, char *str,
|
|
|
|
+ libxl_vscsi_hctl *pdev_hctl,
|
|
|
|
+ libxl_vscsi_pdev *pdev)
|
|
|
|
+{
|
|
|
|
+ int rc = ERROR_INVAL;
|
|
|
|
+ struct xlu__vscsi_target *tgt;
|
|
|
|
+ static const char xen_pvscsi[] = XLU_SYSFS_TARGET_PVSCSI;
|
|
|
|
+
|
|
|
|
+ /* First get hctl representation of config item */
|
|
|
|
+ if (xlu__vscsi_parse_dev(cfg, str, pdev_hctl))
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ /* Check if a SCSI target item exists for the config item */
|
|
|
|
+ if (access(xen_pvscsi, F_OK) == 0) {
|
|
|
|
+ tgt = calloc(1, sizeof(*tgt));
|
|
|
|
+ if (!tgt) {
|
|
|
|
+ rc = ERROR_NOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ tgt->cfg = cfg;
|
|
|
|
+ tgt->pdev_hctl = pdev_hctl;
|
|
|
|
+ tgt->pdev = pdev;
|
|
|
|
+ snprintf(tgt->path, sizeof(tgt->path), "%s", xen_pvscsi);
|
|
|
|
+ if (xlu__vscsi_find_target_wwn(tgt) == true) {
|
|
|
|
+ LOG(cfg, "'%s' maps to '%s(%s)'", str, tgt->path, tgt->udev_path);
|
|
|
|
+ libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_WWN);
|
|
|
|
+ if (asprintf(&pdev->u.wwn.m, "naa.%s:%llu", tgt->wwn, tgt->lun) < 0) {
|
|
|
|
+ rc = ERROR_NOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ free(tgt);
|
|
|
|
+ } else {
|
|
|
|
+ /* Assume xenlinux backend */
|
|
|
|
+ libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_HCTL);
|
|
|
|
+ libxl_vscsi_hctl_copy(ctx, &pdev->u.hctl.m, pdev_hctl);
|
|
|
|
+ }
|
|
|
|
+ rc = 0;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* WWN as understood by pvops */
|
|
|
|
+static int xlu__vscsi_wwn_to_pdev(XLU_Config *cfg, char *str, libxl_vscsi_pdev *pdev)
|
|
|
|
+{
|
|
|
|
+ int rc = ERROR_INVAL;
|
|
|
|
+ unsigned long long lun;
|
|
|
|
+ char wwn[XLU_WWN_LEN + 1];
|
|
|
|
+
|
|
|
|
+ memset(wwn, 0, sizeof(wwn));
|
|
|
|
+ if (sscanf(str, "naa.%16[0-9a-fA-F]:%llu", wwn, &lun) == 2) {
|
|
|
|
+ libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_WWN);
|
|
|
|
+ pdev->u.wwn.m = strdup(str);
|
|
|
|
+ rc = pdev->u.wwn.m ? 0 : ERROR_NOMEM;
|
|
|
|
+ }
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int xlu__vscsi_parse_pdev(XLU_Config *cfg, libxl_ctx *ctx, char *str,
|
|
|
|
+ libxl_vscsi_pdev *pdev)
|
|
|
|
+{
|
|
|
|
+ int rc = ERROR_INVAL;
|
|
|
|
+ libxl_vscsi_hctl pdev_hctl;
|
|
|
|
+
|
|
|
|
+ libxl_vscsi_hctl_init(&pdev_hctl);
|
|
|
|
+ if (strncmp(str, "/dev/", 5) == 0) {
|
|
|
|
+ rc = xlu__vscsi_dev_to_pdev(cfg, ctx, str, &pdev_hctl, pdev);
|
|
|
|
+ } else if (strncmp(str, "naa.", 4) == 0) {
|
|
|
|
+ rc = xlu__vscsi_wwn_to_pdev(cfg, str, pdev);
|
|
|
|
+ } else if (xlu__vscsi_parse_hctl(str, &pdev_hctl) == 0) {
|
|
|
|
+ /* Either xenlinux, or pvops with properly configured alias in sysfs */
|
|
|
|
+ libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_HCTL);
|
|
|
|
+ libxl_vscsi_hctl_copy(ctx, &pdev->u.hctl.m, &pdev_hctl);
|
|
|
|
+ rc = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (rc == 0) {
|
|
|
|
+ pdev->p_devname = strdup(str);
|
|
|
|
+ if (!pdev->p_devname)
|
|
|
|
+ rc = ERROR_NOMEM;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ libxl_vscsi_hctl_dispose(&pdev_hctl);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_parse(XLU_Config *cfg, libxl_ctx *ctx, const char *str,
|
|
|
|
+ libxl_device_vscsictrl *new_ctrl,
|
|
|
|
+ libxl_device_vscsidev *new_dev)
|
|
|
|
+{
|
|
|
|
+ int rc;
|
|
|
|
+ char *tmp, *pdev, *vdev, *fhost;
|
|
|
|
+
|
|
|
|
+ tmp = strdup(str);
|
|
|
|
+ if (!tmp) {
|
|
|
|
+ rc = ERROR_NOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pdev = strtok(tmp, ",");
|
|
|
|
+ vdev = strtok(NULL, ",");
|
|
|
|
+ fhost = strtok(NULL, ",");
|
|
|
|
+ if (!(pdev && vdev)) {
|
|
|
|
+ LOG(cfg, "invalid devspec: '%s'\n", str);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pdev = xlu__vscsi_trim_string(pdev);
|
|
|
|
+ vdev = xlu__vscsi_trim_string(vdev);
|
|
|
|
+
|
|
|
|
+ rc = xlu__vscsi_parse_pdev(cfg, ctx, pdev, &new_dev->pdev);
|
|
|
|
+ if (rc) {
|
|
|
|
+ LOG(cfg, "failed to parse %s, rc == %d", pdev, rc);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (xlu__vscsi_parse_hctl(vdev, &new_dev->vdev)) {
|
|
|
|
+ LOG(cfg, "invalid '%s', expecting hst:chn:tgt:lun", vdev);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ new_ctrl->idx = new_dev->vdev.hst;
|
|
|
|
+
|
|
|
|
+ if (fhost) {
|
|
|
|
+ fhost = xlu__vscsi_trim_string(fhost);
|
|
|
|
+ if (strcmp(fhost, "feature-host") == 0) {
|
|
|
|
+ libxl_defbool_set(&new_ctrl->scsi_raw_cmds, true);
|
|
|
|
+ } else {
|
|
|
|
+ LOG(cfg, "invalid option '%s', expecting %s", fhost, "feature-host");
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ } else
|
|
|
|
+ libxl_defbool_set(&new_ctrl->scsi_raw_cmds, false);
|
|
|
|
+ rc = 0;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ free(tmp);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_get_ctrl(XLU_Config *cfg, libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ const char *str,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ libxl_device_vscsidev *dev,
|
|
|
|
+ libxl_device_vscsictrl *existing,
|
|
|
|
+ bool *found_existing)
|
|
|
|
+{
|
|
|
|
+ libxl_device_vscsictrl *vscsictrls = NULL, *tmp;
|
|
|
|
+ int rc, found_ctrl = -1, i;
|
|
|
|
+ int num_ctrls;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ rc = xlu_vscsi_parse(cfg, ctx, str, ctrl, dev);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ /* Look for existing vscsictrl for given domain */
|
|
|
|
+ vscsictrls = libxl_device_vscsictrl_list(ctx, domid, &num_ctrls);
|
|
|
|
+ if (vscsictrls) {
|
|
|
|
+ for (i = 0; i < num_ctrls; ++i) {
|
|
|
|
+ if (vscsictrls[i].idx == dev->vdev.hst) {
|
|
|
|
+ found_ctrl = i;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (found_ctrl == -1) {
|
|
|
|
+ *found_existing = false;
|
|
|
|
+ } else {
|
|
|
|
+ *found_existing = true;
|
|
|
|
+ tmp = vscsictrls + found_ctrl;
|
|
|
|
+
|
|
|
|
+ /* Check if the vdev address is already taken */
|
|
|
|
+ for (i = 0; i < tmp->num_vscsidevs; ++i) {
|
|
|
|
+ if (tmp->vscsidevs[i].vdev.chn == dev->vdev.chn &&
|
|
|
|
+ tmp->vscsidevs[i].vdev.tgt == dev->vdev.tgt &&
|
|
|
|
+ tmp->vscsidevs[i].vdev.lun == dev->vdev.lun) {
|
|
|
|
+ unsigned long long lun = dev->vdev.lun;
|
|
|
|
+ LOG(cfg, "vdev '%u:%u:%u:%llu' is already used.\n",
|
|
|
|
+ dev->vdev.hst, dev->vdev.chn, dev->vdev.tgt, lun);
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (libxl_defbool_val(ctrl->scsi_raw_cmds) !=
|
|
|
|
+ libxl_defbool_val(tmp->scsi_raw_cmds)) {
|
|
|
|
+ LOG(cfg, "different feature-host setting: "
|
|
|
|
+ "existing ctrl has it %s, new ctrl has it %s\n",
|
|
|
|
+ libxl_defbool_val(ctrl->scsi_raw_cmds) ? "set" : "unset",
|
|
|
|
+ libxl_defbool_val(tmp->scsi_raw_cmds) ? "set" : "unset");
|
|
|
|
+ rc = ERROR_INVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ libxl_device_vscsictrl_copy(ctx, existing, tmp);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ if (vscsictrls) {
|
|
|
|
+ for (i = 0; i < num_ctrls; ++i)
|
|
|
|
+ libxl_device_vscsictrl_dispose(vscsictrls + i);
|
|
|
|
+ free(vscsictrls);
|
|
|
|
+ }
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_detach(XLU_Config *cfg, libxl_ctx *ctx, uint32_t domid, char *str)
|
|
|
|
+{
|
|
|
|
+ libxl_device_vscsidev dev = { };
|
|
|
|
+ libxl_device_vscsictrl ctrl = { };
|
|
|
|
+ int rc;
|
|
|
|
+ char *tmp = NULL;
|
|
|
|
+
|
|
|
|
+ libxl_device_vscsictrl_init(&ctrl);
|
|
|
|
+ libxl_device_vscsidev_init(&dev);
|
|
|
|
+
|
|
|
|
+ /* Create a dummy cfg */
|
|
|
|
+ if (asprintf(&tmp, "0:0:0:0,%s", str) < 0) {
|
|
|
|
+ LOG(cfg, "asprintf failed while removing %s from domid %u", str, domid);
|
|
|
|
+ rc = ERROR_FAIL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = xlu_vscsi_parse(cfg, ctx, tmp, &ctrl, &dev);
|
|
|
|
+ if (rc) goto out;
|
|
|
|
+
|
|
|
|
+ rc = libxl_device_vscsidev_remove(ctx, domid, &dev, NULL);
|
|
|
|
+ switch (rc) {
|
|
|
|
+ case ERROR_NOTFOUND:
|
|
|
|
+ LOG(cfg, "detach failed: %s does not exist in domid %u", str, domid);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ free(tmp);
|
|
|
|
+ libxl_device_vscsidev_dispose(&dev);
|
|
|
|
+ libxl_device_vscsictrl_dispose(&ctrl);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_config_add(XLU_Config *cfg,
|
|
|
|
+ libxl_ctx *ctx,
|
|
|
|
+ const char *str,
|
|
|
|
+ int *num_vscsis,
|
|
|
|
+ libxl_device_vscsictrl **vscsis)
|
|
|
|
+{
|
|
|
|
+ int rc, i;
|
|
|
|
+ libxl_device_vscsidev dev = { };
|
|
|
|
+ libxl_device_vscsictrl *tmp_ctrl, ctrl = { };
|
|
|
|
+ bool ctrl_found = false;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * #1: parse the devspec and place it in temporary ctrl+dev part
|
|
|
|
+ * #2: find existing vscsictrl with number vdev.hst
|
|
|
|
+ * if found, append the vscsidev to this vscsictrl
|
|
|
|
+ * #3: otherwise, create new vscsictrl and append vscsidev
|
|
|
|
+ * Note: vdev.hst does not represent the index named "num_vscsis",
|
|
|
|
+ * it is a private index used just in the config file
|
|
|
|
+ */
|
|
|
|
+ libxl_device_vscsictrl_init(&ctrl);
|
|
|
|
+ libxl_device_vscsidev_init(&dev);
|
|
|
|
+
|
|
|
|
+ rc = xlu_vscsi_parse(cfg, ctx, str, &ctrl, &dev);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ if (*num_vscsis) {
|
|
|
|
+ for (i = 0; i < *num_vscsis; i++) {
|
|
|
|
+ tmp_ctrl = *vscsis + i;
|
|
|
|
+ if (tmp_ctrl->idx == dev.vdev.hst) {
|
|
|
|
+ libxl_device_vscsictrl_append_vscsidev(ctx, tmp_ctrl, &dev);
|
|
|
|
+ ctrl_found = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!ctrl_found || !*num_vscsis) {
|
|
|
|
+ tmp_ctrl = realloc(*vscsis, sizeof(ctrl) * (*num_vscsis + 1));
|
|
|
|
+ if (!tmp_ctrl) {
|
|
|
|
+ LOG(cfg, "realloc #%d failed", *num_vscsis + 1);
|
|
|
|
+ rc = ERROR_NOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ *vscsis = tmp_ctrl;
|
|
|
|
+ tmp_ctrl = *vscsis + *num_vscsis;
|
|
|
|
+ libxl_device_vscsictrl_init(tmp_ctrl);
|
|
|
|
+
|
|
|
|
+ libxl_device_vscsictrl_copy(ctx, tmp_ctrl, &ctrl);
|
|
|
|
+
|
|
|
|
+ libxl_device_vscsictrl_append_vscsidev(ctx, tmp_ctrl, &dev);
|
|
|
|
+
|
|
|
|
+ (*num_vscsis)++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+out:
|
|
|
|
+ libxl_device_vscsidev_dispose(&dev);
|
|
|
|
+ libxl_device_vscsictrl_dispose(&ctrl);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+#else /* ! __linux__ */
|
|
|
|
+int xlu_vscsi_get_ctrl(XLU_Config *cfg, libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ const char *str,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ libxl_device_vscsidev *dev,
|
|
|
|
+ libxl_device_vscsictrl *existing,
|
|
|
|
+ bool *found_existing)
|
|
|
|
+{
|
|
|
|
+ return ERROR_INVAL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_parse(XLU_Config *cfg,
|
|
|
|
+ libxl_ctx *ctx,
|
|
|
|
+ const char *str,
|
|
|
|
+ libxl_device_vscsictrl *new_ctrl,
|
|
|
|
+ libxl_device_vscsidev *new_dev)
|
|
|
|
+{
|
|
|
|
+ return ERROR_INVAL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_detach(XLU_Config *cfg,
|
|
|
|
+ libxl_ctx *ctx,
|
|
|
|
+ uint32_t domid,
|
|
|
|
+ char *str)
|
|
|
|
+{
|
|
|
|
+ return ERROR_INVAL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int xlu_vscsi_config_add(XLU_Config *cfg,
|
|
|
|
+ libxl_ctx *ctx,
|
|
|
|
+ const char *str,
|
|
|
|
+ int *num_vscsis,
|
|
|
|
+ libxl_device_vscsictrl **vscsis)
|
|
|
|
+{
|
|
|
|
+ return ERROR_INVAL;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
Index: xen-4.7.0-testing/tools/libxl/libxlutil.h
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/libxlutil.h
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/libxlutil.h
|
|
|
|
@@ -118,6 +118,25 @@ int xlu_rdm_parse(XLU_Config *cfg, libxl
|
|
|
|
int xlu_vif_parse_rate(XLU_Config *cfg, const char *rate,
|
|
|
|
libxl_device_nic *nic);
|
|
|
|
|
|
|
|
+/* Fill ctrl/dev with device described in str (pdev,vdev[,options]) */
|
|
|
|
+int xlu_vscsi_get_ctrl(XLU_Config *cfg, libxl_ctx *ctx, uint32_t domid,
|
|
|
|
+ const char *str,
|
|
|
|
+ libxl_device_vscsictrl *ctrl,
|
|
|
|
+ libxl_device_vscsidev *dev,
|
|
|
|
+ libxl_device_vscsictrl *existing,
|
|
|
|
+ bool *found_existing);
|
|
|
|
+/* Parse config string and fill provided vscsi ctrl and vscsi device */
|
|
|
|
+int xlu_vscsi_parse(XLU_Config *cfg, libxl_ctx *ctx, const char *str,
|
|
|
|
+ libxl_device_vscsictrl *new_ctrl,
|
|
|
|
+ libxl_device_vscsidev *new_dev);
|
|
|
|
+/* Detach vscsi device described in config string (pdev,vdev[,options]) */
|
|
|
|
+int xlu_vscsi_detach(XLU_Config *cfg, libxl_ctx *ctx, uint32_t domid, char *str);
|
|
|
|
+/* Add vscsi device described in config string (pdev,vdev[,options]) to d_config */
|
|
|
|
+int xlu_vscsi_config_add(XLU_Config *cfg,
|
|
|
|
+ libxl_ctx *ctx,
|
|
|
|
+ const char *str,
|
|
|
|
+ int *num_vscsis,
|
|
|
|
+ libxl_device_vscsictrl **vscsis);
|
|
|
|
#endif /* LIBXLUTIL_H */
|
|
|
|
|
|
|
|
/*
|
|
|
|
Index: xen-4.7.0-testing/tools/libxl/xl.h
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/xl.h
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/xl.h
|
|
|
|
@@ -89,6 +89,9 @@ int main_channellist(int argc, char **ar
|
|
|
|
int main_blockattach(int argc, char **argv);
|
|
|
|
int main_blocklist(int argc, char **argv);
|
|
|
|
int main_blockdetach(int argc, char **argv);
|
|
|
|
+int main_vscsiattach(int argc, char **argv);
|
|
|
|
+int main_vscsilist(int argc, char **argv);
|
|
|
|
+int main_vscsidetach(int argc, char **argv);
|
|
|
|
int main_vtpmattach(int argc, char **argv);
|
|
|
|
int main_vtpmlist(int argc, char **argv);
|
|
|
|
int main_vtpmdetach(int argc, char **argv);
|
|
|
|
Index: xen-4.7.0-testing/tools/libxl/xl_cmdimpl.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/xl_cmdimpl.c
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/xl_cmdimpl.c
|
|
|
|
@@ -1325,7 +1325,7 @@ static void parse_config_data(const char
|
|
|
|
long l, vcpus = 0;
|
|
|
|
XLU_Config *config;
|
|
|
|
XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
|
|
|
|
- *usbctrls, *usbdevs;
|
|
|
|
+ *usbctrls, *usbdevs, *vscsictrls;
|
|
|
|
XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
|
|
|
|
int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
|
2014-05-13 19:13:17 +02:00
|
|
|
int pci_power_mgmt = 0;
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -1855,6 +1855,17 @@ static void parse_config_data(const char
|
2014-05-13 19:13:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 09:45:05 +02:00
|
|
|
+ if (!xlu_cfg_get_list(config, "vscsi", &vscsictrls, 0, 0)) {
|
|
|
|
+ int num_vscsi_items = 0;
|
|
|
|
+ d_config->num_vscsictrls = 0;
|
|
|
|
+ d_config->vscsictrls = NULL;
|
|
|
|
+ while ((buf = xlu_cfg_get_listitem (vscsictrls, num_vscsi_items)) != NULL) {
|
|
|
|
+ if (xlu_vscsi_config_add(config, ctx, buf, &d_config->num_vscsictrls, &d_config->vscsictrls))
|
|
|
|
+ exit(1);
|
|
|
|
+ num_vscsi_items++;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
|
|
|
|
d_config->num_vtpms = 0;
|
|
|
|
d_config->vtpms = NULL;
|
2016-05-03 09:45:05 +02:00
|
|
|
@@ -7416,6 +7427,218 @@ int main_blockdetach(int argc, char **ar
|
2014-05-13 19:13:17 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
+int main_vscsiattach(int argc, char **argv)
|
|
|
|
+{
|
|
|
|
+ uint32_t domid;
|
2016-05-03 09:45:05 +02:00
|
|
|
+ int opt, rc;
|
|
|
|
+ XLU_Config *config = NULL;
|
|
|
|
+ libxl_device_vscsictrl ctrl, existing;
|
|
|
|
+ libxl_device_vscsidev dev;
|
|
|
|
+ bool found_existing = false;
|
|
|
|
+ char *str = NULL, *feat_buf = NULL;
|
|
|
|
+ char *json;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+ SWITCH_FOREACH_OPT(opt, "", NULL, "scsi-attach", 1) {
|
|
|
|
+ /* No options */
|
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ if (argc < 4 || argc > 5) {
|
2014-05-13 19:13:17 +02:00
|
|
|
+ help("scsi-attach");
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &domid) < 0) {
|
|
|
|
+ fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ optind++;
|
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ if (argc == 5) {
|
|
|
|
+ if (asprintf(&feat_buf, ",%s", argv[4]) < 0) {
|
2016-05-03 09:45:05 +02:00
|
|
|
+ perror("asprintf");
|
|
|
|
+ return 1;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
|
|
|
+ if (asprintf(&str, "%s,%s%s", argv[2], argv[3], feat_buf ?: "") < 0) {
|
2014-05-13 19:13:17 +02:00
|
|
|
+ perror("asprintf");
|
2016-05-03 09:45:05 +02:00
|
|
|
+ rc = 1;
|
|
|
|
+ goto out;;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ libxl_device_vscsictrl_init(&existing);
|
|
|
|
+ libxl_device_vscsictrl_init(&ctrl);
|
|
|
|
+ libxl_device_vscsidev_init(&dev);
|
|
|
|
+
|
|
|
|
+ config = xlu_cfg_init(stderr, "command line");
|
|
|
|
+ if (!config) {
|
|
|
|
+ fprintf(stderr, "Failed to allocate for configuration\n");
|
|
|
|
+ rc = 1;
|
|
|
|
+ goto out;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ /* Parse config string and store result */
|
|
|
|
+ rc = xlu_vscsi_get_ctrl(config, ctx, domid, str, &ctrl, &dev, &existing, &found_existing);
|
|
|
|
+ if (rc < 0)
|
|
|
|
+ goto out;
|
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ if (dryrun_only) {
|
2016-05-03 09:45:05 +02:00
|
|
|
+ libxl_device_vscsictrl *tmp = found_existing ? &existing : &ctrl;
|
|
|
|
+ libxl_device_vscsictrl_append_vscsidev(ctx, tmp , &dev);
|
|
|
|
+ json = libxl_device_vscsictrl_to_json(ctx, tmp);
|
2014-05-13 19:13:17 +02:00
|
|
|
+ printf("vscsi: %s\n", json);
|
|
|
|
+ free(json);
|
|
|
|
+ if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
|
2016-05-03 09:45:05 +02:00
|
|
|
+ rc = 0;
|
|
|
|
+ goto out;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ /* Finally add the device */
|
|
|
|
+ if (found_existing) {
|
|
|
|
+ if (libxl_device_vscsidev_add(ctx, domid, &dev, NULL)) {
|
|
|
|
+ fprintf(stderr, "libxl_device_vscsidev_add failed\n");
|
|
|
|
+ rc = 1;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ libxl_device_vscsictrl_append_vscsidev(ctx, &ctrl, &dev);
|
|
|
|
+ if (libxl_device_vscsictrl_add(ctx, domid, &ctrl, NULL)) {
|
|
|
|
+ fprintf(stderr, "libxl_device_vscsictrl_add failed.\n");
|
|
|
|
+ rc = 1;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
|
|
|
+ rc = 0;
|
|
|
|
+out:
|
|
|
|
+ if (config)
|
|
|
|
+ xlu_cfg_destroy(config);
|
|
|
|
+ libxl_device_vscsictrl_dispose(&existing);
|
|
|
|
+ libxl_device_vscsictrl_dispose(&ctrl);
|
|
|
|
+ libxl_device_vscsidev_dispose(&dev);
|
|
|
|
+ free(str);
|
2014-05-13 19:13:17 +02:00
|
|
|
+ free(feat_buf);
|
2016-05-03 09:45:05 +02:00
|
|
|
+ return rc;
|
2014-05-13 19:13:17 +02:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int main_vscsilist(int argc, char **argv)
|
|
|
|
+{
|
|
|
|
+ int opt;
|
2016-05-03 09:45:05 +02:00
|
|
|
+ uint32_t domid;
|
|
|
|
+ libxl_device_vscsictrl *vscsictrls;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ libxl_vscsiinfo vscsiinfo;
|
2016-05-03 09:45:05 +02:00
|
|
|
+ int num_ctrls, h, d;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+ SWITCH_FOREACH_OPT(opt, "", NULL, "scsi-list", 1) {
|
|
|
|
+ /* No options */
|
|
|
|
+ }
|
|
|
|
+ if (argc < 2) {
|
|
|
|
+ help("scsi-list");
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
|
|
|
+ /* Idx BE state ctrl p_hst v_hst state */
|
2014-05-13 19:13:17 +02:00
|
|
|
+ printf("%-3s %-3s %-5s %-5s %-10s %-10s %-5s\n",
|
2016-05-03 09:45:05 +02:00
|
|
|
+ "Idx", "BE", "state", "ctrl", "phy-hctl", "vir-hctl", "devstate");
|
2014-05-13 19:13:17 +02:00
|
|
|
+ for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
|
|
|
|
+ if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
|
|
|
|
+ fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+ vscsictrls = libxl_device_vscsictrl_list(ctx, domid, &num_ctrls);
|
|
|
|
+ if (!vscsictrls)
|
2014-05-13 19:13:17 +02:00
|
|
|
+ continue;
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
|
|
|
+ for (h = 0; h < num_ctrls; ++h) {
|
|
|
|
+ for (d = 0; d < vscsictrls[h].num_vscsidevs; d++) {
|
|
|
|
+ if (!libxl_device_vscsictrl_getinfo(ctx, domid, &vscsictrls[h],
|
|
|
|
+ &vscsictrls[h].vscsidevs[d],
|
|
|
|
+ &vscsiinfo)) {
|
|
|
|
+ char pdev[64], vdev[64];
|
|
|
|
+ unsigned long long lun;
|
|
|
|
+ switch (vscsiinfo.pdev.type) {
|
|
|
|
+ case LIBXL_VSCSI_PDEV_TYPE_HCTL:
|
|
|
|
+ lun = vscsiinfo.pdev.u.hctl.m.lun;
|
|
|
|
+ snprintf(pdev, sizeof(pdev), "%u:%u:%u:%llu",
|
|
|
|
+ vscsiinfo.pdev.u.hctl.m.hst,
|
|
|
|
+ vscsiinfo.pdev.u.hctl.m.chn,
|
|
|
|
+ vscsiinfo.pdev.u.hctl.m.tgt,
|
|
|
|
+ lun);
|
|
|
|
+ break;
|
|
|
|
+ case LIBXL_VSCSI_PDEV_TYPE_WWN:
|
|
|
|
+ snprintf(pdev, sizeof(pdev), "%s",
|
|
|
|
+ vscsiinfo.pdev.u.wwn.m);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ pdev[0] = '\0';
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ lun = vscsiinfo.vdev.lun;
|
|
|
|
+ snprintf(vdev, sizeof(vdev), "%u:%u:%u:%llu",
|
|
|
|
+ vscsiinfo.vdev.hst,
|
|
|
|
+ vscsiinfo.vdev.chn,
|
|
|
|
+ vscsiinfo.vdev.tgt,
|
|
|
|
+ lun);
|
|
|
|
+ /* Idx BE state Sta */
|
|
|
|
+ printf("%-3d %-3d %-5d %-5d %-10s %-10s %d\n",
|
|
|
|
+ vscsiinfo.devid,
|
|
|
|
+ vscsiinfo.backend_id,
|
|
|
|
+ vscsiinfo.vscsictrl_state,
|
|
|
|
+ vscsiinfo.backend_id,
|
|
|
|
+ pdev, vdev,
|
|
|
|
+ vscsiinfo.vscsidev_state);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ libxl_vscsiinfo_dispose(&vscsiinfo);
|
|
|
|
+ }
|
|
|
|
+ libxl_device_vscsictrl_dispose(&vscsictrls[h]);
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+ free(vscsictrls);
|
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int main_vscsidetach(int argc, char **argv)
|
|
|
|
+{
|
|
|
|
+ int opt;
|
2016-05-03 09:45:05 +02:00
|
|
|
+ char *dom = argv[1], *str = argv[2];
|
2014-05-13 19:13:17 +02:00
|
|
|
+ uint32_t domid;
|
2016-05-03 09:45:05 +02:00
|
|
|
+ XLU_Config *config = NULL;
|
|
|
|
+ int rc = 0;
|
2014-05-13 19:13:17 +02:00
|
|
|
+
|
|
|
|
+ SWITCH_FOREACH_OPT(opt, "", NULL, "scsi-detach", 1) {
|
|
|
|
+ /* No options */
|
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ if (argc < 3) {
|
|
|
|
+ help("scsi-detach");
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
2014-05-13 19:13:17 +02:00
|
|
|
+ if (libxl_domain_qualifier_to_domid(ctx, dom, &domid) < 0) {
|
|
|
|
+ fprintf(stderr, "%s is an invalid domain identifier\n", dom);
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
2016-05-03 09:45:05 +02:00
|
|
|
+ config = xlu_cfg_init(stderr, "command line");
|
|
|
|
+ if (!config) {
|
|
|
|
+ fprintf(stderr, "Failed to allocate for configuration\n");
|
|
|
|
+ goto out;
|
2014-05-13 19:13:17 +02:00
|
|
|
+ }
|
2016-05-03 09:45:05 +02:00
|
|
|
+
|
|
|
|
+ rc = xlu_vscsi_detach(config, ctx, domid, str);
|
|
|
|
+ if (rc)
|
|
|
|
+ fprintf(stderr, "scsi-detach %s %s failed: %d\n", dom, str, rc);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ if (config)
|
|
|
|
+ xlu_cfg_destroy(config);
|
|
|
|
+ return !!rc;
|
2014-05-13 19:13:17 +02:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
int main_vtpmattach(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int opt;
|
2016-03-25 23:10:02 +01:00
|
|
|
Index: xen-4.7.0-testing/tools/libxl/xl_cmdtable.c
|
2015-10-06 23:17:42 +02:00
|
|
|
===================================================================
|
2016-03-25 23:10:02 +01:00
|
|
|
--- xen-4.7.0-testing.orig/tools/libxl/xl_cmdtable.c
|
|
|
|
+++ xen-4.7.0-testing/tools/libxl/xl_cmdtable.c
|
- Add patches from proposed upstream series to load BIOS's from
the toolstack instead of embedding in hvmloader
http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01626.html
0001-libxc-Rework-extra-module-initialisation.patch,
0002-libxc-Prepare-a-start-info-structure-for-hvmloader.patch,
0003-configure-define-SEABIOS_PATH-and-OVMF_PATH.patch,
0004-firmware-makefile-install-BIOS-blob.patch,
0005-libxl-Load-guest-BIOS-from-file.patch,
0006-xen-Move-the-hvm_start_info-C-representation-from-li.patch,
0007-hvmloader-Grab-the-hvm_start_info-pointer.patch,
0008-hvmloader-Locate-the-BIOS-blob.patch,
0009-hvmloader-Check-modules-whereabouts-in-perform_tests.patch,
0010-hvmloader-Load-SeaBIOS-from-hvm_start_info-modules.patch,
0011-hvmloader-Load-OVMF-from-modules.patch,
0012-hvmloader-Specific-bios_load-function-required.patch,
0013-hvmloader-Always-build-in-SeaBIOS-and-OVMF-loader.patch,
0014-configure-do-not-depend-on-SEABIOS_PATH-or-OVMF_PATH.patch
- Enable support for UEFI on x86_64 using the ovmf-x86_64-ms.bin
firmware from qemu-ovmf-x86_64. The firmware is preloaded with
Microsoft keys to more closely resemble firmware on real hardware
FATE#320490
OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=416
2016-04-13 21:43:10 +02:00
|
|
|
@@ -354,6 +354,21 @@ struct cmd_spec cmd_table[] = {
|
2014-05-13 19:13:17 +02:00
|
|
|
"Destroy a domain's virtual block device",
|
|
|
|
"<Domain> <DevId>",
|
|
|
|
},
|
|
|
|
+ { "scsi-attach",
|
|
|
|
+ &main_vscsiattach, 1, 1,
|
|
|
|
+ "Attach a dom0 SCSI device to a domain.",
|
|
|
|
+ "<Domain> <PhysDevice> <VirtDevice>",
|
|
|
|
+ },
|
|
|
|
+ { "scsi-list",
|
|
|
|
+ &main_vscsilist, 0, 0,
|
2016-05-03 09:45:05 +02:00
|
|
|
+ "List all dom0 SCSI devices currently attached to a domain.",
|
2014-05-13 19:13:17 +02:00
|
|
|
+ "<Domain(s)>",
|
|
|
|
+ },
|
|
|
|
+ { "scsi-detach",
|
|
|
|
+ &main_vscsidetach, 0, 1,
|
|
|
|
+ "Detach a specified SCSI device from a domain.",
|
|
|
|
+ "<Domain> <VirtDevice>",
|
|
|
|
+ },
|
|
|
|
{ "vtpm-attach",
|
|
|
|
&main_vtpmattach, 1, 1,
|
|
|
|
"Create a new virtual TPM device",
|