xen/libxl.pvscsi.patch
Charles Arnold 92ed83b0e8 - 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 19:43:10 +00:00

1189 lines
44 KiB
Diff

* local-fate316613-pvscsi-staging-4.4
git://github.com/olafhering/xen.git : local-fate316613-pvscsi-staging-4.4
Implement pvscsi in xl/libxl
fate#316613 , https://fate.suse.com/316613
10bd594 pvscsi: move parse_vscsi_config code block to avoid fuzz
06914e1 Merge pull request #4 from aaannz/pvscsi
fe65eb3 define SUSE PVSCSI extension for 3rd party use
8a34a98 pvscsi: check null pointer in libxl__add_vscsis
09fa151 pvscsi: avoid double assignment of host devices
aa88928 pvscsi: fix double free in scsi-attach
2de1507 pvscsi: update comments about libxl.so ABI
483f7e9 Merge pull request #3 from aaannz/pvscsi
d98458c Xen4.2 ABI compat
73744a5 preserve Xen4.2 ABI, WIP
0f8e701 fix minor memory leaks
1b1c55d pvscsi: correct comment for DEFINE_DEVICES_ADD
6f50972 pvscsi: move libxl__add_vscsis call
6fd1327 pvscsi: add comment for DEFINE_DEVICES_ADD
e4bf1fd pvscsi: fix DEFINE_DEVICE_REMOVE destroy
51b63a6 pvscsi: man pages
e461042 pvscsi: implememnt single device scsi-detach
540e524 Merge pull request #2 from aaannz/pvscsi
919a851 implement vscsi-attach
e07db68 fix indentation
b087b9d pvscsi: implement simple scsi-detach
824f286 pvscsi: simplify sysfs parsing in parse_vscsi_config
977d81d pvscsi: include stddef in xl_cmdimpl.c to get offsetof
ee2e7e5 Merge pull request #1 from aaannz/pvscsi
7de6f49 support character devices too
c84381b allow /dev/sda as scsi devspec
f11e3a2 pvscsi
Index: xen-4.7.0-testing/docs/man/xl.cfg.pod.5
===================================================================
--- xen-4.7.0-testing.orig/docs/man/xl.cfg.pod.5
+++ xen-4.7.0-testing/docs/man/xl.cfg.pod.5
@@ -517,6 +517,36 @@ value is optional if this is a guest dom
=back
+=item B<vscsi=[ "VSCSI_SPEC_STRING", "VSCSI_SPEC_STRING", ...]>
+
+Specifies the PVSCSI devices to be provided to the guest. PVSCSI passes
+dom0 SCSI devices as-is to the guest.
+
+Each B<VSCSI_SPEC_STRING> is a mapping from dom0 SCSI devices to guest visible
+SCSI devices, like 'pvdev,vdev[,option]'. Example: '/dev/sdm,3:0:4:5,feature-host'
+
+=over 4
+
+=item C<pdev>
+
+Specifies the dom0 visible SCSI device. The string can be either a device path
+like to a block device like /dev/disk/by-id/scsi-XYZ. Or it can be a device path
+to a char device like /dev/sg5. Or it can be specified in the SCSI notation
+HOST:CHANNEL:TARGET:LUN. Note that the latter format is unreliable because
+the HOST value can change across dom0 reboots.
+
+=item C<vdev>
+
+Specifies how the SCSI device is mapped into the guest. The notation is in
+SCSI notation HOST:CHANNEL:TARGET:LUN. HOST in this case means a virthal
+SCSI host within the guest.
+
+=item C<option>
+
+Right now only one option is recognized: feature-host.
+
+=back
+
=item B<vfb=[ "VFB_SPEC_STRING", "VFB_SPEC_STRING", ...]>
Specifies the paravirtual framebuffer devices which should be supplied
Index: xen-4.7.0-testing/docs/man/xl.pod.1
===================================================================
--- xen-4.7.0-testing.orig/docs/man/xl.pod.1
+++ xen-4.7.0-testing/docs/man/xl.pod.1
@@ -1416,6 +1416,26 @@ List virtual trusted platform modules fo
=back
+=head2 PVSCSI DEVICES
+
+=over 4
+
+=item B<scsi-attach> I<domain-id> I<pdev> I<vdev> I<[feature-host]>
+
+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>.
+Note that the whole virtual SCSI host with all its devices is removed.
+This is a BUG!
+
+=item B<vscsi-list> I<domain-id> I<[domain-id] ...>
+
+List vscsi devices for the domain specified by I<domain-id>.
+
+=back
+
=head1 PCI PASS-THROUGH
=over 4
Index: xen-4.7.0-testing/tools/libxl/libxl.c
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl.c
+++ xen-4.7.0-testing/tools/libxl/libxl.c
@@ -2299,6 +2299,273 @@ int libxl_devid_to_device_vtpm(libxl_ctx
return rc;
}
+/******************************************************************************/
+static int libxl__device_from_vscsi(libxl__gc *gc, uint32_t domid,
+ libxl_device_vscsi *vscsi,
+ libxl__device *device)
+{
+ device->backend_domid = vscsi->backend_domid;
+ device->devid = vscsi->devid;
+ device->domid = domid;
+ device->backend_kind = LIBXL__DEVICE_KIND_VSCSI;
+ device->kind = LIBXL__DEVICE_KIND_VSCSI;
+
+ return 0;
+}
+
+void libxl__device_vscsi_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_vscsi *vscsi,
+ libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+ flexarray_t *front;
+ flexarray_t *back;
+ libxl__device *device;
+ unsigned int rc, i;
+
+ i = 2 * (4 + (3 * vscsi->num_vscsi_devs));
+ front = flexarray_make(gc, 4, 1);
+ back = flexarray_make(gc, i, 1);
+
+ if (vscsi->devid == -1) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ GCNEW(device);
+ rc = libxl__device_from_vscsi(gc, domid, vscsi, device);
+ if ( rc != 0 ) goto out;
+
+ /* get backend device path to check if is already present */
+ char *backend_path;
+ unsigned int ndirs = 0;
+ backend_path = libxl__device_backend_path(gc, device);
+ if (!libxl__xs_directory(gc, XBT_NULL, backend_path, &ndirs) || !ndirs) {
+ /* backend does not exist => vscsi host does not exist */
+ flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
+ flexarray_append_pair(back, "online", "1");
+ flexarray_append_pair(back, "state", "1");
+ flexarray_append_pair(back, "feature-host", GCSPRINTF("%d", !!vscsi->feature_host));
+
+ flexarray_append_pair(front, "backend-id", GCSPRINTF("%d", vscsi->backend_domid));
+ flexarray_append_pair(front, "state", "1");
+ }
+
+ for (i = 0; i < vscsi->num_vscsi_devs; i++) {
+ libxl_vscsi_dev *v = vscsi->vscsi_devs + i;
+ if (ndirs) {
+ unsigned int nb = 0;
+ /* vhost exist, check if not overwriting records */
+ if (libxl__xs_directory(gc, XBT_NULL,
+ GCSPRINTF("%s/vscsi-devs/dev-%u", backend_path, v->vscsi_dev_id),
+ &nb) && nb) {
+ /* trigger device removal by forwarding state to XenbusStateClosing */
+ if (v->remove)
+ flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/state", v->vscsi_dev_id), "5");
+ continue;
+ }
+ }
+ flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/p-dev", v->vscsi_dev_id),
+ GCSPRINTF("%u:%u:%u:%u", v->p_hst, v->p_chn, v->p_tgt, v->p_lun));
+ flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/v-dev", v->vscsi_dev_id),
+ GCSPRINTF("%u:%u:%u:%u", vscsi->v_hst, v->v_chn, v->v_tgt, v->v_lun));
+ flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/state", v->vscsi_dev_id), "1");
+ }
+
+ aodev->dev = device;
+ if (ndirs == 0) {
+ libxl__device_generic_add(gc, XBT_NULL, device,
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
+ NULL);
+
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ libxl__wait_device_connection(egc, aodev);
+ }
+ else {
+ /* we added only new vscsi devices, write them and trigger vscsi host reconfiguration */
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ xs_transaction_t t;
+retry_transaction:
+ t = xs_transaction_start(ctx->xsh);
+ libxl__xs_writev(gc, t, backend_path,
+ libxl__xs_kvs_of_flexarray(gc, back, back->count));
+ xs_write(ctx->xsh, t, GCSPRINTF("%s/state", backend_path), "7", 2);
+ if(!xs_transaction_end(ctx->xsh, t, 0)) {
+ if (errno == EAGAIN) {
+ goto retry_transaction;
+ }
+ else {
+ LOGE(ERROR, "xs transaction failed");
+ return;
+ }
+ }
+ libxl__wait_for_backend(gc, backend_path, "4");
+
+retry_transaction2:
+ t = xs_transaction_start(ctx->xsh);
+ for (i = 0; i < vscsi->num_vscsi_devs; i++) {
+ libxl_vscsi_dev *v = vscsi->vscsi_devs + i;
+ if (v->remove) {
+ char *tmppath, *tmpval;
+ tmppath = GCSPRINTF("%s/vscsi-devs/dev-%u/state", backend_path, v->vscsi_dev_id);
+ tmpval = libxl__xs_read(gc, t, tmppath);
+ if (tmpval && strcmp(tmpval, "6") == 0) {
+ tmppath = GCSPRINTF("%s/vscsi-devs/dev-%u/state", backend_path, v->vscsi_dev_id);
+ xs_rm(ctx->xsh, t, tmppath);
+ tmppath = GCSPRINTF("%s/vscsi-devs/dev-%u/p-dev", backend_path, v->vscsi_dev_id);
+ xs_rm(ctx->xsh, t, tmppath);
+ tmppath = GCSPRINTF("%s/vscsi-devs/dev-%u/v-dev", backend_path, v->vscsi_dev_id);
+ xs_rm(ctx->xsh, t, tmppath);
+ tmppath = GCSPRINTF("%s/vscsi-devs/dev-%u", backend_path, v->vscsi_dev_id);
+ xs_rm(ctx->xsh, t, tmppath);
+ } else {
+ LOGE(ERROR, "%s: %s has %s, expected 6", __func__, tmppath, tmpval);
+ }
+ }
+ }
+ if(!xs_transaction_end(ctx->xsh, t, 0)) {
+ if (errno == EAGAIN) {
+ goto retry_transaction2;
+ }
+ else {
+ LOGE(ERROR, "xs transaction failed");
+ return;
+ }
+ }
+ /* as we are not adding new device, skip waiting for it */
+ libxl__ao_complete(egc, aodev->ao, 0);
+ }
+
+ rc = 0;
+out:
+ aodev->rc = rc;
+ if(rc) aodev->callback(egc, aodev);
+ return;
+}
+
+libxl_device_vscsi *libxl_device_vscsi_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+ GC_INIT(ctx);
+
+ libxl_device_vscsi *vscsi_hosts = NULL;
+ char *fe_path;
+ char **dir;
+ unsigned int ndirs = 0;
+
+ fe_path = libxl__sprintf(gc, "%s/device/vscsi", libxl__xs_get_dompath(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ if (dir && ndirs) {
+ libxl_device_vscsi *vscsi, *end;
+ vscsi_hosts = calloc(ndirs, sizeof(*vscsi_hosts));
+ for (vscsi = vscsi_hosts, end = vscsi_hosts + ndirs; vscsi_hosts && vscsi < end; ++vscsi, ++dir) {
+ unsigned int vd_dirs = 0, i;
+ char *tmp;
+ char **vscsi_devs_dir;
+ const char *vscsi_devs_path, *be_path = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s/backend", fe_path, *dir));
+
+ libxl_device_vscsi_init(vscsi);
+
+ vscsi->devid = atoi(*dir);
+
+ tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s/backend-id", fe_path, *dir));
+ vscsi->backend_domid = atoi(tmp);
+
+ vscsi_devs_path = libxl__sprintf(gc, "%s/vscsi-devs", be_path);
+ vscsi_devs_dir = libxl__xs_directory(gc, XBT_NULL, vscsi_devs_path, &vd_dirs);
+ if (vscsi_devs_dir && vd_dirs) {
+ vscsi->vscsi_devs = calloc(vd_dirs, sizeof(*vscsi->vscsi_devs));
+ vscsi->num_vscsi_devs = vd_dirs;
+ for (i = 0; i < vd_dirs; i++, vscsi_devs_dir++) {
+ unsigned int vscsi_dev_id;
+ if (sscanf(*vscsi_devs_dir, "dev-%u", &vscsi_dev_id) != 1) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "%s/scsi-devs/%s failed to parse", be_path, *vscsi_devs_dir);
+ continue;
+ }
+ vscsi->vscsi_devs[i].vscsi_dev_id = vscsi_dev_id;
+ tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/vscsi-devs/dev-%u/p-dev", be_path, vscsi_dev_id));
+ if (tmp)
+ sscanf(tmp, "%u:%u:%u:%u", &vscsi->vscsi_devs[i].p_hst, &vscsi->vscsi_devs[i].p_chn, &vscsi->vscsi_devs[i].p_tgt, &vscsi->vscsi_devs[i].p_lun);
+ tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/vscsi-devs/dev-%u/v-dev", be_path, vscsi_dev_id));
+ if (tmp)
+ sscanf(tmp, "%u:%u:%u:%u", &vscsi->v_hst, &vscsi->vscsi_devs[i].v_chn, &vscsi->vscsi_devs[i].v_tgt, &vscsi->vscsi_devs[i].v_lun);
+ }
+ }
+ }
+ }
+ *num = ndirs;
+
+ GC_FREE;
+ return vscsi_hosts;
+}
+
+int libxl_device_vscsi_getinfo(libxl_ctx *ctx,
+ uint32_t domid,
+ libxl_device_vscsi *vscsi_host,
+ libxl_vscsi_dev *vscsi_dev,
+ libxl_vscsiinfo *vscsiinfo)
+{
+ GC_INIT(ctx);
+ char *dompath, *vscsipath;
+ char *val;
+ int rc = 0;
+
+ libxl_vscsiinfo_init(vscsiinfo);
+ dompath = libxl__xs_get_dompath(gc, domid);
+ vscsiinfo->devid = vscsi_host->devid;
+ vscsiinfo->p_hst = vscsi_dev->p_hst;
+ vscsiinfo->p_chn = vscsi_dev->p_chn;
+ vscsiinfo->p_tgt = vscsi_dev->p_tgt;
+ vscsiinfo->p_lun = vscsi_dev->p_lun;
+ vscsiinfo->v_hst = vscsi_host->v_hst;
+ vscsiinfo->v_chn = vscsi_dev->v_chn;
+ vscsiinfo->v_tgt = vscsi_dev->v_tgt;
+ vscsiinfo->v_lun = vscsi_dev->v_lun;
+
+ 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 err;
+ }
+ if(!libxl__xs_read(gc, XBT_NULL, vscsiinfo->backend)) {
+ goto err;
+ }
+
+ 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->vscsi_host_state = val ? strtoul(val, NULL, 10) : -1;
+
+ val = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/event-channel", vscsipath));
+ vscsiinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+ val = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/ring-ref", vscsipath));
+ vscsiinfo->rref = 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, vscsi_dev->vscsi_dev_id));
+ vscsiinfo->vscsi_dev_state = val ? strtoul(val, NULL, 10) : -1;
+
+ goto exit;
+err:
+ rc = ERROR_FAIL;
+exit:
+ GC_FREE;
+ return rc;
+}
/******************************************************************************/
@@ -4250,6 +4517,8 @@ out:
* libxl_device_vfb_destroy
* libxl_device_usbctrl_remove
* libxl_device_usbctrl_destroy
+ * libxl_device_vscsi_remove
+ * libxl_device_vscsi_destroy
*/
#define DEFINE_DEVICE_REMOVE_EXT(type, remtype, removedestroy, f) \
int libxl_device_##type##_##removedestroy(libxl_ctx *ctx, \
@@ -4315,6 +4584,10 @@ DEFINE_DEVICE_REMOVE_CUSTOM(usbctrl, des
* 1. add support for secondary consoles to xenconsoled
* 2. dynamically add/remove qemu chardevs via qmp messages. */
+/* vscsi */
+DEFINE_DEVICE_REMOVE(vscsi, remove, 0)
+DEFINE_DEVICE_REMOVE(vscsi, destroy, 1)
+
#undef DEFINE_DEVICE_REMOVE
#undef DEFINE_DEVICE_REMOVE_CUSTOM
#undef DEFINE_DEVICE_REMOVE_EXT
@@ -4328,6 +4601,7 @@ DEFINE_DEVICE_REMOVE_CUSTOM(usbctrl, des
* libxl_device_vtpm_add
* libxl_device_usbctrl_add
* libxl_device_usbdev_add
+ * libxl_device_vscsi_add
*/
#define DEFINE_DEVICE_ADD(type) \
@@ -4365,6 +4639,9 @@ DEFINE_DEVICE_ADD(usbctrl)
/* usb */
DEFINE_DEVICE_ADD(usbdev)
+/* vscsi */
+DEFINE_DEVICE_ADD(vscsi)
+
#undef DEFINE_DEVICE_ADD
/******************************************************************************/
@@ -7328,6 +7605,20 @@ out:
return rc;
}
+/* libxl.so.4.4 ABI compatilibity hack - do not do this at home */
+static libxl_device_vscsi_suse* libxl__global_vscsi_list_suse;
+
+libxl_device_vscsi_suse* libxl_get_vscsi_devices_suse(void)
+{
+ return libxl__global_vscsi_list_suse;
+}
+
+void libxl_set_vscsi_devices_suse(libxl_device_vscsi_suse* vscsi_host)
+{
+ libxl__global_vscsi_list_suse = vscsi_host;
+}
+/* EOF libxl.so.4.4 ABI compat hack */
+
/*
* Local variables:
* mode: C
Index: xen-4.7.0-testing/tools/libxl/libxl.h
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl.h
+++ xen-4.7.0-testing/tools/libxl/libxl.h
@@ -1721,6 +1721,26 @@ libxl_device_vtpm *libxl_device_vtpm_lis
int libxl_device_vtpm_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_vtpm *vtpm, libxl_vtpminfo *vtpminfo);
+/* Virtual SCSI */
+int libxl_device_vscsi_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vscsi *vscsi,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vscsi_remove(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vscsi *vscsi,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vscsi_destroy(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vscsi *vscsi,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vscsi *libxl_device_vscsi_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vscsi_getinfo(libxl_ctx *ctx,
+ uint32_t domid,
+ libxl_device_vscsi *vscsi_host,
+ libxl_vscsi_dev *vscsi_dev,
+ libxl_vscsiinfo *vscsiinfo);
+
/* Keyboard */
int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
const libxl_asyncop_how *ao_how)
@@ -2063,6 +2083,27 @@ int libxl_fd_set_nonblock(libxl_ctx *ctx
#include <libxl_event.h>
+/* libxl.so.4.4 ABI compatilibity hack - do not do this at home */
+
+/*
+ * LIBXL_HAVE_DEVICE_PVSCSI_SUSE
+ *
+ * If this is defined, set pvscsi devices through helpers
+ * libxl_get_vscsi_devices_suse and libxl_set_vscsi_devices_suse.
+ *
+ * If this is not defined, pvscsi is either unavailable or available through
+ * libxl_domain_config structure
+ */
+#define LIBXL_HAVE_DEVICE_PVSCSI_SUSE 1
+typedef struct {
+ libxl_device_vscsi* vscsi_devices;
+ int num_vscsi_devices;
+} libxl_device_vscsi_suse;
+
+libxl_device_vscsi_suse* libxl_get_vscsi_devices_suse(void);
+void libxl_set_vscsi_devices_suse(libxl_device_vscsi_suse* vscsi_host);
+/* EOF libxl.so.4.4 ABI compat hack */
+
#endif /* LIBXL_H */
/*
Index: xen-4.7.0-testing/tools/libxl/libxl_create.c
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl_create.c
+++ xen-4.7.0-testing/tools/libxl/libxl_create.c
@@ -1227,6 +1227,7 @@ static void domcreate_rebuild_done(libxl
libxl__multidev_begin(ao, &dcs->multidev);
dcs->multidev.callback = domcreate_launch_dm;
libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev);
+ libxl__add_vscsis(egc, ao, domid, d_config, &dcs->multidev);
libxl__multidev_prepared(egc, &dcs->multidev, 0);
return;
Index: xen-4.7.0-testing/tools/libxl/libxl_device.c
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl_device.c
+++ xen-4.7.0-testing/tools/libxl/libxl_device.c
@@ -616,6 +616,7 @@ void libxl__multidev_prepared(libxl__egc
* The following functions are defined:
* libxl__add_disks
* libxl__add_nics
+ * libxl__add_vscsis
* libxl__add_vtpms
* libxl__add_usbctrls
* libxl__add_usbs
@@ -640,9 +641,31 @@ DEFINE_DEVICES_ADD(nic)
DEFINE_DEVICES_ADD(vtpm)
DEFINE_DEVICES_ADD(usbctrl)
DEFINE_DEVICES_ADD(usbdev)
+// DEFINE_DEVICES_ADD(vscsi)
#undef DEFINE_DEVICES_ADD
+// to preserve libxl.so.4.4 ABI custom define libxl__add_vscsi
+void libxl__add_vscsis(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+ libxl_domain_config *d_config,
+ libxl__multidev *multidev)
+{
+ AO_GC;
+ int i;
+
+ libxl_device_vscsi *vhosts;
+ int num_vhosts;
+ libxl_device_vscsi_suse* vscsi_hosts_suse = libxl_get_vscsi_devices_suse();
+ if (!vscsi_hosts_suse)
+ return;
+ num_vhosts = vscsi_hosts_suse->num_vscsi_devices;
+ vhosts = vscsi_hosts_suse->vscsi_devices;
+ for (i = 0; i < num_vhosts; i++) {
+ libxl__ao_device *aodev = libxl__multidev_prepare(multidev);
+ libxl__device_vscsi_add(egc, domid, vhosts+i, aodev);
+ }
+}
+
/******************************************************************************/
int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
Index: xen-4.7.0-testing/tools/libxl/libxl_internal.h
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl_internal.h
+++ xen-4.7.0-testing/tools/libxl/libxl_internal.h
@@ -1219,6 +1219,7 @@ _hidden int libxl__device_disk_setdefaul
_hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
uint32_t domid);
_hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
+_hidden int libxl__device_vscsi_setdefault(libxl__gc *gc, libxl_device_vscsi *vscsi);
_hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
_hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
_hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
@@ -2638,6 +2639,10 @@ _hidden void libxl__device_usbdev_add(li
libxl_device_usbdev *usbdev,
libxl__ao_device *aodev);
+_hidden void libxl__device_vscsi_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_vscsi *vscsi,
+ libxl__ao_device *aodev);
+
/* Internal function to connect a vkb device */
_hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
libxl_device_vkb *vkb);
@@ -3496,6 +3501,10 @@ _hidden void libxl__add_usbdevs(libxl__e
uint32_t domid, libxl_domain_config *d_config,
libxl__multidev *multidev);
+_hidden void libxl__add_vscsis(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+ libxl_domain_config *d_config,
+ libxl__multidev *multidev);
+
/*----- device model creation -----*/
/* First layer; wraps libxl__spawn_spawn. */
Index: xen-4.7.0-testing/tools/libxl/libxl_types.idl
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl_types.idl
+++ xen-4.7.0-testing/tools/libxl/libxl_types.idl
@@ -696,6 +696,26 @@ libxl_device_channel = Struct("device_ch
])),
])
+libxl_vscsi_dev = Struct("vscsi_dev", [
+ ("vscsi_dev_id", libxl_devid),
+ ("remove", bool),
+ ("p_hst", uint32),
+ ("p_chn", uint32),
+ ("p_tgt", uint32),
+ ("p_lun", uint32),
+ ("v_chn", uint32),
+ ("v_tgt", uint32),
+ ("v_lun", uint32),
+ ])
+
+libxl_device_vscsi = Struct("device_vscsi", [
+ ("backend_domid", libxl_domid),
+ ("devid", libxl_devid),
+ ("v_hst", uint32),
+ ("vscsi_devs", Array(libxl_vscsi_dev, "num_vscsi_devs")),
+ ("feature_host", bool),
+ ])
+
libxl_domain_config = Struct("domain_config", [
("c_info", libxl_domain_create_info),
("b_info", libxl_domain_build_info),
@@ -713,6 +733,8 @@ libxl_domain_config = Struct("domain_con
("channels", Array(libxl_device_channel, "num_channels")),
("usbctrls", Array(libxl_device_usbctrl, "num_usbctrls")),
("usbdevs", Array(libxl_device_usbdev, "num_usbdevs")),
+# preserve libxl.so.4.4 ABI
+# ("vscsis", Array(libxl_device_vscsi, "num_vscsis")),
("on_poweroff", libxl_action_on_shutdown),
("on_reboot", libxl_action_on_shutdown),
@@ -771,6 +793,28 @@ libxl_usbctrlinfo = Struct("usbctrlinfo"
("ref_conn", integer),
], dir=DIR_OUT)
+libxl_vscsiinfo = Struct("vscsiinfo", [
+ ("backend", string),
+ ("backend_id", uint32),
+ ("frontend", string),
+ ("frontend_id", uint32),
+ ("devid", libxl_devid),
+ ("p_hst", uint32),
+ ("p_chn", uint32),
+ ("p_tgt", uint32),
+ ("p_lun", uint32),
+ ("vscsi_dev_id", libxl_devid),
+ ("v_hst", uint32),
+ ("v_chn", uint32),
+ ("v_tgt", uint32),
+ ("v_lun", uint32),
+ ("feature_host", bool),
+ ("vscsi_host_state", integer),
+ ("vscsi_dev_state", integer),
+ ("evtch", integer),
+ ("rref", integer),
+ ], dir=DIR_OUT)
+
libxl_vcpuinfo = Struct("vcpuinfo", [
("vcpuid", uint32),
("cpu", uint32),
Index: xen-4.7.0-testing/tools/libxl/libxl_types_internal.idl
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/libxl_types_internal.idl
+++ xen-4.7.0-testing/tools/libxl/libxl_types_internal.idl
@@ -24,6 +24,7 @@ libxl__device_kind = Enumeration("device
(8, "VTPM"),
(9, "VUSB"),
(10, "QUSB"),
+ (11, "VSCSI"),
])
libxl__console_backend = Enumeration("console_backend", [
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
@@ -17,6 +17,7 @@
#include "libxl_osdeps.h"
#include <stdio.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -34,6 +35,7 @@
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
+#include <dirent.h>
#include <xen/hvm/e820.h>
#include "libxl.h"
@@ -635,6 +637,122 @@ static void set_default_nic_values(libxl
}
}
+static char *vscsi_trim_string(char *s)
+{
+ unsigned int len;
+
+ while (isspace(*s))
+ s++;
+ len = strlen(s);
+ while (len-- > 1 && isspace(s[len]))
+ s[len] = '\0';
+ return s;
+}
+
+static void parse_vscsi_config(libxl_device_vscsi *vscsi_host,
+ libxl_vscsi_dev *vscsi_dev,
+ char *buf)
+{
+ char *pdev, *vdev, *fhost;
+ unsigned int hst, chn, tgt, lun;
+
+ libxl_device_vscsi_init(vscsi_host);
+ pdev = strtok(buf, ",");
+ vdev = strtok(NULL, ",");
+ fhost = strtok(NULL, ",");
+ if (!(pdev && vdev)) {
+ fprintf(stderr, "invalid vscsi= devspec: '%s'\n", buf);
+ exit(1);
+ }
+
+ pdev = vscsi_trim_string(pdev);
+ vdev = vscsi_trim_string(vdev);
+
+ if (strncmp(pdev, "/dev/", 5) == 0) {
+#ifdef __linux__
+ struct stat pdev_stat;
+ char pdev_sysfs_path[PATH_MAX];
+ const char *type;
+ int result = 0;
+ DIR *dirp;
+ struct dirent *de;
+
+ /* stat pdev to get device's sysfs entry */
+ if (stat (pdev, &pdev_stat) == -1) {
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', device not found or cannot be read\n", "pdev", pdev, buf);
+ exit(1);
+ }
+ if (S_ISBLK (pdev_stat.st_mode)) {
+ type = "block";
+ } else if (S_ISCHR (pdev_stat.st_mode)) {
+ type = "char";
+ } else {
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', not a valid block or char device\n", "pdev", pdev, buf);
+ exit(1);
+ }
+
+ /* get pdev scsi address - subdir of scsi_device sysfs entry */
+ snprintf(pdev_sysfs_path, sizeof(pdev_sysfs_path), "/sys/dev/%s/%u:%u/device/scsi_device",
+ type,
+ major(pdev_stat.st_rdev),
+ minor(pdev_stat.st_rdev));
+
+ dirp = opendir(pdev_sysfs_path);
+ if (!dirp) {
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', cannot find scsi device\n", "pdev", pdev, buf);
+ exit(1);
+ }
+
+ while ((de = readdir(dirp))) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+
+ if (sscanf(de->d_name, "%u:%u:%u:%u", &hst, &chn, &tgt, &lun) != 4) {
+ fprintf(stderr, "vscsi: ignoring unknown devspec '%s' for device '%s'\n",
+ de->d_name, pdev);
+ continue;
+ }
+ result = 1;
+ break;
+ }
+ closedir(dirp);
+
+ if (!result) {
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', cannot find scsi device in sysfs\n", "pdev", pdev, buf);
+ exit(1);
+ }
+#else
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', expecting hst:chn:tgt:lun\n", "pdev", pdev, buf);
+ exit(1);
+#endif
+ } else if (sscanf(pdev, "%u:%u:%u:%u", &hst, &chn, &tgt, &lun) != 4) {
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', expecting hst:chn:tgt:lun\n", "pdev", pdev, buf);
+ exit(1);
+ }
+ vscsi_dev->p_hst = hst;
+ vscsi_dev->p_chn = chn;
+ vscsi_dev->p_tgt = tgt;
+ vscsi_dev->p_lun = lun;
+
+ if (sscanf(vdev, "%u:%u:%u:%u", &hst, &chn, &tgt, &lun) != 4) {
+ fprintf(stderr, "vscsi: invalid %s '%s' in vscsi= devspec: '%s', expecting hst:chn:tgt:lun\n", "vdev", vdev, buf);
+ exit(1);
+ }
+ vscsi_host->v_hst = hst;
+ vscsi_dev->v_chn = chn;
+ vscsi_dev->v_tgt = tgt;
+ vscsi_dev->v_lun = lun;
+
+ if (fhost) {
+ fhost = vscsi_trim_string(fhost);
+ vscsi_host->feature_host = strcmp(fhost, "feature-host") == 0;
+ if (!vscsi_host->feature_host) {
+ fprintf(stderr, "vscsi: invalid option '%s' in vscsi= devspec: '%s', expecting %s\n", fhost, buf, "feature-host");
+ exit(1);
+ }
+ }
+}
+
static void split_string_into_string_list(const char *str,
const char *delim,
libxl_string_list *psl)
@@ -1326,7 +1444,7 @@ static void parse_config_data(const char
XLU_Config *config;
XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
*usbctrls, *usbdevs;
- XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
+ XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs, *vscsis;
int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
int pci_power_mgmt = 0;
int pci_msitranslate = 0;
@@ -1855,6 +1973,66 @@ static void parse_config_data(const char
}
}
+ if (!xlu_cfg_get_list(config, "vscsi", &vscsis, 0, 0)) {
+ int cnt_vscsi_devs = 0;
+
+ /*
+ * to preserve libxl.so.4.4 ABI, do not store vscsis to d_config
+ * we are using extra array for that
+ */
+ libxl_device_vscsi* vscsi_hosts = calloc(1, sizeof(libxl_device_vscsi));
+ int num_vscsi_hosts = 0;
+
+ while ((buf = xlu_cfg_get_listitem (vscsis, cnt_vscsi_devs)) != NULL) {
+ libxl_vscsi_dev vscsi_dev = { };
+ libxl_device_vscsi vscsi_host = { };
+ libxl_device_vscsi *host;
+ char *tmp_buf;
+ int num_vscsis, host_found = 0;
+
+ /*
+ * #1: parse the devspec and place it in temporary host+dev part
+ * #2: find existing vscsi_host with number v_hst
+ * if found, append the vscsi_dev to this vscsi_host
+ * #3: otherwise, create new vscsi_host and append vscsi_dev
+ * Note: v_hst does not represent the index named "num_vscsis",
+ * it is a private index used just in the config file
+ */
+ tmp_buf = strdup(buf);
+ parse_vscsi_config(&vscsi_host, &vscsi_dev, tmp_buf);
+ free(tmp_buf);
+
+ if (num_vscsi_hosts) {
+ for (num_vscsis = 0; num_vscsis < num_vscsi_hosts; num_vscsis++) {
+ if (vscsi_hosts[num_vscsis].v_hst == vscsi_host.v_hst) {
+ host = vscsi_hosts + num_vscsis;
+ host->vscsi_devs = realloc(host->vscsi_devs, sizeof(libxl_vscsi_dev) * (host->num_vscsi_devs + 1));
+ vscsi_dev.vscsi_dev_id = host->num_vscsi_devs;
+ memcpy(host->vscsi_devs + host->num_vscsi_devs, &vscsi_dev, sizeof(vscsi_dev));
+ host->num_vscsi_devs++;
+ host_found = 1;
+ break;
+ }
+ }
+ }
+ if (!host_found || !num_vscsi_hosts) {
+ vscsi_hosts = realloc(vscsi_hosts, sizeof(libxl_device_vscsi) * (num_vscsi_hosts + 1));
+ vscsi_host.vscsi_devs = malloc(sizeof(libxl_vscsi_dev));
+ vscsi_dev.vscsi_dev_id = 0;
+ memcpy(vscsi_host.vscsi_devs, &vscsi_dev, sizeof(vscsi_dev));
+ vscsi_host.num_vscsi_devs++;
+ vscsi_host.devid = num_vscsi_hosts;
+ memcpy(vscsi_hosts + num_vscsi_hosts, &vscsi_host, sizeof(vscsi_host));
+ num_vscsi_hosts++;
+ }
+ cnt_vscsi_devs++;
+ }
+ libxl_device_vscsi_suse* vscsis_suse = calloc(1, sizeof(libxl_device_vscsi_suse));
+ vscsis_suse->vscsi_devices = vscsi_hosts;
+ vscsis_suse->num_vscsi_devices = num_vscsi_hosts;
+ libxl_set_vscsi_devices_suse(vscsis_suse);
+ }
+
if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
d_config->num_vtpms = 0;
d_config->vtpms = NULL;
@@ -7412,6 +7590,256 @@ int main_blockdetach(int argc, char **ar
return rc;
}
+int main_vscsiattach(int argc, char **argv)
+{
+ int opt;
+ int num_hosts, i = 0, found_host = -1, res = 0;
+ libxl_vscsi_dev *vscsi_dev;
+ libxl_device_vscsi *vscsi_host, *vscsi_tmphst;
+ libxl_device_vscsi *vscsi_hosts_existing = NULL;
+ uint32_t domid;
+ char *tmp_buf, *feat_buf = NULL;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "scsi-attach", 1) {
+ /* No options */
+ }
+
+ if (argc < 4) {
+ help("scsi-attach");
+ return 1;
+ }
+ if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &domid) < 0) {
+ fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+ return 1;
+ }
+ ++optind;
+
+ if (argc < 4) {
+ fprintf(stderr, "scsi-attach: 3 options required.\n");
+ return 1;
+ }
+ if (argc == 5) {
+ if (asprintf(&feat_buf, ",%s", argv[4]) < 0) {
+ perror("asprintf");
+ return 1;
+ }
+ }
+ if (asprintf(&tmp_buf, "%s,%s%s", argv[2], argv[3], feat_buf ?: "") < 0) {
+ perror("asprintf");
+ return 1;
+ }
+
+ vscsi_dev = calloc(1, sizeof(*vscsi_dev));
+ vscsi_host = calloc(1, sizeof(*vscsi_host));
+ if (!(vscsi_dev && vscsi_host)) {
+ fprintf(stderr, "%s ENOMEM\n", __func__);
+ res = 1;
+ goto vscsi_attach_out;
+ }
+ parse_vscsi_config(vscsi_host, vscsi_dev, tmp_buf);
+
+ /* look for existing vscsi_host for given domain */
+ vscsi_hosts_existing = libxl_device_vscsi_list(ctx, domid, &num_hosts);
+ if (vscsi_hosts_existing) {
+ for (i = 0; i < num_hosts; ++i) {
+ int j;
+ for (j = 0; j < vscsi_hosts_existing[i].num_vscsi_devs; j++) {
+ if (vscsi_hosts_existing[i].vscsi_devs[j].p_hst == vscsi_dev->p_hst &&
+ vscsi_hosts_existing[i].vscsi_devs[j].p_chn == vscsi_dev->p_chn &&
+ vscsi_hosts_existing[i].vscsi_devs[j].p_tgt == vscsi_dev->p_tgt &&
+ vscsi_hosts_existing[i].vscsi_devs[j].p_lun == vscsi_dev->p_lun) {
+ fprintf(stderr, "Host device '%u:%u:%u:%u' is already in use"
+ " by guest vscsi specification '%u:%u:%u:%u'.\n",
+ vscsi_dev->p_hst, vscsi_dev->p_chn, vscsi_dev->p_tgt, vscsi_dev->p_lun,
+ vscsi_hosts_existing[i].v_hst, vscsi_dev->v_chn, vscsi_dev->v_tgt, vscsi_dev->v_lun);
+ res = 1;
+ goto vscsi_attach_out;
+ }
+ }
+ if (vscsi_host->v_hst == vscsi_hosts_existing[i].v_hst) {
+ found_host = i;
+ break;
+ }
+ }
+ }
+ if (found_host == -1) {
+ vscsi_host->devid = i;
+ vscsi_host->vscsi_devs = vscsi_dev;
+ vscsi_host->num_vscsi_devs = 1;
+ vscsi_tmphst = vscsi_host;
+ } else {
+ /* look if the vdev address is not taken */
+ vscsi_tmphst = vscsi_hosts_existing + found_host;
+ for (i = 0; i < vscsi_tmphst->num_vscsi_devs; ++i) {
+ if (vscsi_tmphst->vscsi_devs[i].v_chn == vscsi_dev->v_chn &&
+ vscsi_tmphst->vscsi_devs[i].v_tgt == vscsi_dev->v_tgt &&
+ vscsi_tmphst->vscsi_devs[i].v_lun == vscsi_dev->v_lun) {
+ fprintf(stderr, "Target vscsi specification '%u:%u:%u:%u' is already taken\n",
+ vscsi_tmphst->v_hst, vscsi_dev->v_chn,
+ vscsi_dev->v_tgt, vscsi_dev->v_lun);
+ res = 1;
+ goto vscsi_attach_out;
+ }
+ }
+ vscsi_tmphst->vscsi_devs = realloc(vscsi_tmphst->vscsi_devs,
+ sizeof(libxl_vscsi_dev) *
+ (vscsi_tmphst->num_vscsi_devs + 1));
+ if (vscsi_tmphst->vscsi_devs == NULL) {
+ fprintf(stderr, "%s ENOMEM\n", __func__);
+ res = 1;
+ goto vscsi_attach_out;
+ }
+ vscsi_dev->vscsi_dev_id = vscsi_tmphst->num_vscsi_devs;
+ memcpy(vscsi_tmphst->vscsi_devs + vscsi_tmphst->num_vscsi_devs,
+ vscsi_dev, sizeof(*vscsi_dev));
+ vscsi_tmphst->num_vscsi_devs++;
+ }
+
+ if (dryrun_only) {
+ char* json = libxl_device_vscsi_to_json(ctx, vscsi_tmphst);
+ printf("vscsi: %s\n", json);
+ free(json);
+ if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+ }
+ else if (libxl_device_vscsi_add(ctx, domid, vscsi_tmphst, 0)) {
+ fprintf(stderr, "libxl_device_vscsi_add failed.\n");
+ res = 1;
+ }
+
+vscsi_attach_out:
+ if (vscsi_hosts_existing) {
+ for (i = 0; i < num_hosts; ++i)
+ libxl_device_vscsi_dispose(vscsi_hosts_existing+i);
+ free(vscsi_hosts_existing);
+ }
+ free(vscsi_host);
+ free(vscsi_dev);
+ free(tmp_buf);
+ free(feat_buf);
+ return res;
+}
+
+int main_vscsilist(int argc, char **argv)
+{
+ int opt;
+ libxl_device_vscsi *vscsi_hosts;
+ libxl_vscsiinfo vscsiinfo;
+ int num_hosts, h, d;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "scsi-list", 1) {
+ /* No options */
+ }
+ if (argc < 2) {
+ help("scsi-list");
+ return 1;
+ }
+ /* Idx BE state host p_hst v_hst state */
+ printf("%-3s %-3s %-5s %-5s %-10s %-10s %-5s\n",
+ "Idx", "BE", "state", "host", "phy-hctl", "vir-hctl", "devstate");
+ for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+ uint32_t domid;
+ if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+ fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+ continue;
+ }
+ if (!(vscsi_hosts = libxl_device_vscsi_list(ctx, domid, &num_hosts))) {
+ continue;
+ }
+ for (h = 0; h < num_hosts; ++h) {
+ for (d = 0; d < vscsi_hosts[h].num_vscsi_devs; d++) {
+ if (!libxl_device_vscsi_getinfo(ctx, domid, &vscsi_hosts[h], &vscsi_hosts[h].vscsi_devs[d], &vscsiinfo)) {
+ char pdev[64], vdev[64];
+ snprintf(pdev, sizeof(pdev), "%u:%u:%u:%u",
+ vscsiinfo.p_hst, vscsiinfo.p_chn, vscsiinfo.p_tgt, vscsiinfo.p_lun);
+ snprintf(vdev, sizeof(vdev), "%u:%u:%u:%u",
+ vscsiinfo.v_hst, vscsiinfo.v_chn, vscsiinfo.v_tgt, vscsiinfo.v_lun);
+ /* Idx BE state Sta */
+ printf("%-3d %-3d %-5d %-5d %-10s %-10s %d\n",
+ vscsiinfo.devid,
+ vscsiinfo.backend_id,
+ vscsiinfo.vscsi_host_state,
+ vscsiinfo.backend_id,
+ pdev, vdev,
+ vscsiinfo.vscsi_dev_state);
+
+ libxl_vscsiinfo_dispose(&vscsiinfo);
+ }
+ }
+ libxl_device_vscsi_dispose(&vscsi_hosts[h]);
+ }
+ free(vscsi_hosts);
+ }
+ return 0;
+}
+
+int main_vscsidetach(int argc, char **argv)
+{
+ int opt;
+ libxl_vscsi_dev *vscsi_dev, *vd;
+ libxl_device_vscsi *vscsi_host, *vh;
+ libxl_device_vscsi *vscsi_hosts;
+ char *tmp_buf, *dom = argv[1], *vdev = argv[2];
+ uint32_t domid;
+ int num_hosts, h, d, found = 0;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "scsi-detach", 1) {
+ /* No options */
+ }
+ if (argc < 3) {
+ help("scsi-detach");
+ return 1;
+ }
+ if (libxl_domain_qualifier_to_domid(ctx, dom, &domid) < 0) {
+ fprintf(stderr, "%s is an invalid domain identifier\n", dom);
+ return 1;
+ }
+ vscsi_hosts = libxl_device_vscsi_list(ctx, domid, &num_hosts);
+ if (!vscsi_hosts)
+ return 0;
+
+ if (asprintf(&tmp_buf, "0:0:0:0,%s", vdev) < 0) {
+ perror("asprintf");
+ return 1;
+ }
+ vscsi_dev = calloc(1, sizeof(*vscsi_dev));
+ vscsi_host = calloc(1, sizeof(*vscsi_host));
+ if (!(vscsi_dev && vscsi_host)) {
+ fprintf(stderr, "%s ENOMEM\n", __func__);
+ goto done;
+ }
+ parse_vscsi_config(vscsi_host, vscsi_dev, tmp_buf);
+
+ for (h = 0; h < num_hosts; ++h) {
+ vh = &vscsi_hosts[h];
+ for (d = 0; !found && d < vh->num_vscsi_devs; d++) {
+#define CMP(member) (vd->member == vscsi_dev->member)
+ vd = &vh->vscsi_devs[d];
+ if (vh->v_hst == vscsi_host->v_hst && CMP(v_chn) && CMP(v_tgt) && CMP(v_lun)) {
+ if (vh->num_vscsi_devs > 1) {
+ vd->remove = true;
+ if (libxl_device_vscsi_add(ctx, domid, vh, 0)) {
+ fprintf(stderr, "libxl_device_vscsi_remove failed.\n");
+ goto done;
+ }
+ } else {
+ libxl_device_vscsi_remove(ctx, domid, vh, 0);
+ }
+ found = 1;
+ }
+#undef CMP
+ }
+ libxl_device_vscsi_dispose(vh);
+ }
+ if (!found)
+ fprintf(stderr, "%s(%u) vdev %s does not exist in domain %s\n", __func__, __LINE__, vdev, dom);
+done:
+ free(vscsi_hosts);
+ free(vscsi_host);
+ free(vscsi_dev);
+ free(tmp_buf);
+ return !found;
+}
+
int main_vtpmattach(int argc, char **argv)
{
int opt;
Index: xen-4.7.0-testing/tools/libxl/xl_cmdtable.c
===================================================================
--- xen-4.7.0-testing.orig/tools/libxl/xl_cmdtable.c
+++ xen-4.7.0-testing/tools/libxl/xl_cmdtable.c
@@ -354,6 +354,21 @@ struct cmd_spec cmd_table[] = {
"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,
+ "List all dom0 SCSI devices currently attached.",
+ "<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",