1190 lines
44 KiB
Diff
1190 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.5.0-testing/docs/man/xl.cfg.pod.5
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/docs/man/xl.cfg.pod.5
|
|
+++ xen-4.5.0-testing/docs/man/xl.cfg.pod.5
|
|
@@ -448,6 +448,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.5.0-testing/docs/man/xl.pod.1
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/docs/man/xl.pod.1
|
|
+++ xen-4.5.0-testing/docs/man/xl.pod.1
|
|
@@ -1323,6 +1323,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.5.0-testing/tools/libxl/libxl.c
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl.c
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl.c
|
|
@@ -2263,6 +2263,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;
|
|
+}
|
|
|
|
/******************************************************************************/
|
|
|
|
@@ -4138,6 +4405,8 @@ out:
|
|
* libxl_device_vkb_destroy
|
|
* libxl_device_vfb_remove
|
|
* libxl_device_vfb_destroy
|
|
+ * libxl_device_vscsi_remove
|
|
+ * libxl_device_vscsi_destroy
|
|
*/
|
|
#define DEFINE_DEVICE_REMOVE(type, removedestroy, f) \
|
|
int libxl_device_##type##_##removedestroy(libxl_ctx *ctx, \
|
|
@@ -4193,6 +4462,10 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
|
|
* 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
|
|
|
|
/******************************************************************************/
|
|
@@ -4202,6 +4475,7 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
|
|
* libxl_device_disk_add
|
|
* libxl_device_nic_add
|
|
* libxl_device_vtpm_add
|
|
+ * libxl_device_vscsi_add
|
|
*/
|
|
|
|
#define DEFINE_DEVICE_ADD(type) \
|
|
@@ -4233,6 +4507,9 @@ DEFINE_DEVICE_ADD(nic)
|
|
/* vtpm */
|
|
DEFINE_DEVICE_ADD(vtpm)
|
|
|
|
+/* vscsi */
|
|
+DEFINE_DEVICE_ADD(vscsi)
|
|
+
|
|
#undef DEFINE_DEVICE_ADD
|
|
|
|
/******************************************************************************/
|
|
@@ -6769,6 +7046,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.5.0-testing/tools/libxl/libxl.h
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl.h
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl.h
|
|
@@ -1228,6 +1228,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)
|
|
@@ -1485,6 +1505,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.5.0-testing/tools/libxl/libxl_create.c
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl_create.c
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl_create.c
|
|
@@ -1141,6 +1141,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.5.0-testing/tools/libxl/libxl_device.c
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl_device.c
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl_device.c
|
|
@@ -541,6 +541,7 @@ void libxl__multidev_prepared(libxl__egc
|
|
* The following functions are defined:
|
|
* libxl__add_disks
|
|
* libxl__add_nics
|
|
+ * libxl__add_vscsis
|
|
* libxl__add_vtpms
|
|
*/
|
|
|
|
@@ -560,10 +561,32 @@ void libxl__multidev_prepared(libxl__egc
|
|
|
|
DEFINE_DEVICES_ADD(disk)
|
|
DEFINE_DEVICES_ADD(nic)
|
|
+// DEFINE_DEVICES_ADD(vscsi)
|
|
DEFINE_DEVICES_ADD(vtpm)
|
|
|
|
#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.5.0-testing/tools/libxl/libxl_internal.h
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl_internal.h
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl_internal.h
|
|
@@ -1079,6 +1079,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);
|
|
@@ -2390,6 +2391,10 @@ _hidden void libxl__device_vtpm_add(libx
|
|
libxl_device_vtpm *vtpm,
|
|
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);
|
|
@@ -3013,6 +3018,10 @@ _hidden void libxl__add_vtpms(libxl__egc
|
|
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.5.0-testing/tools/libxl/libxl_types.idl
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl_types.idl
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl_types.idl
|
|
@@ -540,6 +540,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),
|
|
@@ -553,6 +573,8 @@ libxl_domain_config = Struct("domain_con
|
|
# a channel manifests as a console with a name,
|
|
# see docs/misc/channels.txt
|
|
("channels", Array(libxl_device_channel, "num_channels")),
|
|
+# 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),
|
|
@@ -595,6 +617,28 @@ libxl_vtpminfo = Struct("vtpminfo", [
|
|
("uuid", libxl_uuid),
|
|
], 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.5.0-testing/tools/libxl/libxl_types_internal.idl
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/libxl_types_internal.idl
|
|
+++ xen-4.5.0-testing/tools/libxl/libxl_types_internal.idl
|
|
@@ -22,6 +22,7 @@ libxl__device_kind = Enumeration("device
|
|
(6, "VKBD"),
|
|
(7, "CONSOLE"),
|
|
(8, "VTPM"),
|
|
+ (9, "VSCSI"),
|
|
])
|
|
|
|
libxl__console_backend = Enumeration("console_backend", [
|
|
Index: xen-4.5.0-testing/tools/libxl/xl.h
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/xl.h
|
|
+++ xen-4.5.0-testing/tools/libxl/xl.h
|
|
@@ -83,6 +83,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.5.0-testing/tools/libxl/xl_cmdimpl.c
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/xl_cmdimpl.c
|
|
+++ xen-4.5.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"
|
|
@@ -549,6 +551,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)
|
|
@@ -918,7 +1036,7 @@ static void parse_config_data(const char
|
|
const char *buf;
|
|
long l;
|
|
XLU_Config *config;
|
|
- XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
|
|
+ XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vscsis;
|
|
XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian;
|
|
int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
|
|
int pci_power_mgmt = 0;
|
|
@@ -1421,6 +1539,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;
|
|
@@ -6492,6 +6670,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.5.0-testing/tools/libxl/xl_cmdtable.c
|
|
===================================================================
|
|
--- xen-4.5.0-testing.orig/tools/libxl/xl_cmdtable.c
|
|
+++ xen-4.5.0-testing/tools/libxl/xl_cmdtable.c
|
|
@@ -372,6 +372,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",
|