Create the structures and API's to hold and manage the iSCSI host device. This extends the 'scsi_host' definitions added in commit id '5c811dce'. A future patch will add the XML parsing, but that code requires some infrastructure to be in place first in order to handle the differences between a 'scsi_host' and an 'iSCSI host' device. Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> --- src/conf/domain_audit.c | 20 +++- src/conf/domain_conf.c | 47 ++++++++- src/conf/domain_conf.h | 20 ++++ src/qemu/qemu_cgroup.c | 35 ++++--- src/qemu/qemu_command.c | 74 ++++++++++++--- src/qemu/qemu_hotplug.c | 36 +++++-- src/security/security_apparmor.c | 6 ++ src/security/security_dac.c | 12 +++ src/security/security_selinux.c | 12 +++ src/util/virhostdev.c | 200 +++++++++++++++++++++++++-------------- 10 files changed, 349 insertions(+), 113 deletions(-) diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index ee9baa2..3ad58b0 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -424,12 +424,22 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: { - virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; - if (virAsprintfQuiet(&address, "%s:%d:%d:%d", - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit) < 0) { - VIR_WARN("OOM while encoding audit message"); + if (scsisrc->protocol == + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + /* Follow virDomainAuditDisk && virDomainAuditGenericDev + * and don't audit the networked device. + */ goto cleanup; + } else { + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = + &scsisrc->u.host; + if (virAsprintfQuiet(&address, "%s:%d:%d:%d", + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, + scsihostsrc->unit) < 0) { + VIR_WARN("OOM while encoding audit message"); + goto cleanup; + } } break; } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 53bd1d5..a80530f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1709,6 +1709,17 @@ virDomainHostdevDefPtr virDomainHostdevDefAlloc(void) return def; } +static void +virDomainHostdevSubsysSCSIiSCSIClear(virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc) +{ + if (!iscsisrc) + return; + VIR_FREE(iscsisrc->path); + virStorageNetHostDefFree(iscsisrc->nhosts, iscsisrc->hosts); + virStorageAuthDefFree(iscsisrc->auth); + iscsisrc->auth = NULL; +} + void virDomainHostdevDefClear(virDomainHostdevDefPtr def) { if (!def) @@ -1739,8 +1750,15 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } break; case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: - if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) - VIR_FREE(def->source.subsys.u.scsi.u.host.adapter); + if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi; + if (scsisrc->protocol == + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + virDomainHostdevSubsysSCSIiSCSIClear(&scsisrc->u.iscsi); + } else { + VIR_FREE(scsisrc->u.host.adapter); + } + } break; } } @@ -4320,8 +4338,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, } if (sgio) { - if (def->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { virReportError(VIR_ERR_XML_ERROR, "%s", _("sgio is only supported for scsi host device")); goto error; @@ -10265,6 +10282,22 @@ virDomainHostdevMatchSubsysSCSIHost(virDomainHostdevDefPtr first, } static int +virDomainHostdevMatchSubsysSCSIiSCSI(virDomainHostdevDefPtr first, + virDomainHostdevDefPtr second) +{ + virDomainHostdevSubsysSCSIiSCSIPtr first_iscsisrc = + &first->source.subsys.u.scsi.u.iscsi; + virDomainHostdevSubsysSCSIiSCSIPtr second_iscsisrc = + &second->source.subsys.u.scsi.u.iscsi; + + if (STREQ(first_iscsisrc->hosts[0].name, second_iscsisrc->hosts[0].name) && + STREQ(first_iscsisrc->hosts[0].port, second_iscsisrc->hosts[0].port) && + STREQ(first_iscsisrc->path, second_iscsisrc->path)) + return 1; + return 0; +} + +static int virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, virDomainHostdevDefPtr b) { @@ -10277,7 +10310,11 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: return virDomainHostdevMatchSubsysUSB(a, b); case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: - return virDomainHostdevMatchSubsysSCSIHost(a, b); + if (a->source.subsys.u.scsi.protocol == + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + return virDomainHostdevMatchSubsysSCSIiSCSI(a, b); + else + return virDomainHostdevMatchSubsysSCSIHost(a, b); } return 0; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 56f6735..569b2a0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -396,6 +396,15 @@ typedef enum { VIR_ENUM_DECL(virDomainHostdevSubsysPCIBackend) +typedef enum { + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE, + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI, + + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST, +} virDomainHostdevSCSIProtocolType; + +VIR_ENUM_DECL(virDomainHostdevSubsysSCSIProtocol) + typedef struct _virDomainHostdevSubsysUSB virDomainHostdevSubsysUSB; typedef virDomainHostdevSubsysUSB *virDomainHostdevSubsysUSBPtr; struct _virDomainHostdevSubsysUSB { @@ -424,12 +433,23 @@ struct _virDomainHostdevSubsysSCSIHost { unsigned unit; }; +typedef struct _virDomainHostdevSubsysSCSIiSCSI virDomainHostdevSubsysSCSIiSCSI; +typedef virDomainHostdevSubsysSCSIiSCSI *virDomainHostdevSubsysSCSIiSCSIPtr; +struct _virDomainHostdevSubsysSCSIiSCSI { + char *path; + size_t nhosts; + virStorageNetHostDefPtr hosts; + virStorageAuthDefPtr auth; +}; + typedef struct _virDomainHostdevSubsysSCSI virDomainHostdevSubsysSCSI; typedef virDomainHostdevSubsysSCSI *virDomainHostdevSubsysSCSIPtr; struct _virDomainHostdevSubsysSCSI { + int protocol; /* enum virDomainHostdevSCSIProtocolType */ int sgio; /* enum virDomainDeviceSGIO */ union { virDomainHostdevSubsysSCSIHost host; + virDomainHostdevSubsysSCSIiSCSI iscsi; } u; }; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 3d69b09..795ad90 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -307,18 +307,31 @@ qemuSetupHostdevCGroup(virDomainObjPtr vm, break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: { - virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; - if ((scsi = virSCSIDeviceNew(NULL, - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit, - dev->readonly, - dev->shareable)) == NULL) - goto cleanup; + if (scsisrc->protocol == + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + /* Follow qemuSetupDiskCgroup() and qemuSetImageCgroupInternal() + * which does nothing for non local storage + */ + VIR_DEBUG("Not updating cgroups for hostdev iSCSI path '%s'", + iscsisrc->path); + } else { + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = + &scsisrc->u.host; + if ((scsi = virSCSIDeviceNew(NULL, + scsihostsrc->adapter, + scsihostsrc->bus, + scsihostsrc->target, + scsihostsrc->unit, + dev->readonly, + dev->shareable)) == NULL) + goto cleanup; - if (virSCSIDeviceFileIterate(scsi, - qemuSetupHostSCSIDeviceCgroup, - vm) < 0) - goto cleanup; + if (virSCSIDeviceFileIterate(scsi, + qemuSetupHostSCSIDeviceCgroup, + vm) < 0) + goto cleanup; + } break; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 372ad22..1cf7ba2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5124,13 +5124,11 @@ qemuBuildUSBHostdevUSBDevStr(virDomainHostdevDefPtr dev) return ret; } -char * -qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainHostdevDefPtr dev, - virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED, - qemuBuildCommandLineCallbacksPtr callbacks) +static char * +qemuBuildSCSIHostHostdevDrvStr(virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED, + qemuBuildCommandLineCallbacksPtr callbacks) { - virBuffer buf = VIR_BUFFER_INITIALIZER; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; char *sg = NULL; @@ -5140,10 +5138,64 @@ qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED, scsihostsrc->bus, scsihostsrc->target, scsihostsrc->unit); - if (!sg) - goto error; + return sg; +} + +static char * +qemuBuildSCSIiSCSIHostdevDrvStr(virConnectPtr conn, + virDomainHostdevDefPtr dev) +{ + char *source = NULL; + char *secret = NULL; + char *username = NULL; + virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + + if (conn && iscsisrc->auth) { + const char *protocol = + virStorageNetProtocolTypeToString(VIR_STORAGE_NET_PROTOCOL_ISCSI); + bool encode = false; + int secretType = VIR_SECRET_USAGE_TYPE_ISCSI; + + username = iscsisrc->auth->username; + if (!(secret = qemuGetSecretString(conn, protocol, encode, + iscsisrc->auth, secretType))) + goto cleanup; + } + + /* Rather than pull what we think we want - use the network disk code */ + source = qemuBuildNetworkDriveURI(VIR_STORAGE_NET_PROTOCOL_ISCSI, + iscsisrc->path, + NULL, /* volume */ + iscsisrc->nhosts, + iscsisrc->hosts, + username, secret); - virBufferAsprintf(&buf, "file=/dev/%s,if=none", sg); + cleanup: + VIR_FREE(secret); + return source; +} + +char * +qemuBuildSCSIHostdevDrvStr(virConnectPtr conn, + virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps, + qemuBuildCommandLineCallbacksPtr callbacks) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *source = NULL; + virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(conn, dev))) + goto error; + virBufferAsprintf(&buf, "file=%s,if=none,format=raw", source); + } else { + if (!(source = qemuBuildSCSIHostHostdevDrvStr(dev, qemuCaps, + callbacks))) + goto error; + virBufferAsprintf(&buf, "file=/dev/%s,if=none", source); + } virBufferAsprintf(&buf, ",id=%s-%s", virDomainDeviceAddressTypeToString(dev->info->type), dev->info->alias); @@ -5162,10 +5214,10 @@ qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED, if (virBufferCheckError(&buf) < 0) goto error; - VIR_FREE(sg); + VIR_FREE(source); return virBufferContentAndReset(&buf); error: - VIR_FREE(sg); + VIR_FREE(source); virBufferFreeAndReset(&buf); return NULL; } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6773d50..729744c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1575,11 +1575,18 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, if (qemuPrepareHostdevSCSIDevices(driver, vm->def->name, &hostdev, 1)) { virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; - virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to prepare scsi hostdev: %s:%d:%d:%d"), - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit); + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to prepare scsi hostdev for iSCSI: %s"), + iscsisrc->path); + } else { + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to prepare scsi hostdev: %s:%d:%d:%d"), + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, scsihostsrc->unit); + } return -1; } @@ -3400,11 +3407,20 @@ int qemuDomainDetachHostDevice(virConnectPtr conn, } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: { - virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; - virReportError(VIR_ERR_OPERATION_FAILED, - _("host scsi device %s:%d:%d.%d not found"), - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit); + if (scsisrc->protocol == + VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + virReportError(VIR_ERR_OPERATION_FAILED, + _("host scsi iSCSI path %s not found"), + iscsisrc->path); + } else { + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = + &scsisrc->u.host; + virReportError(VIR_ERR_OPERATION_FAILED, + _("host scsi device %s:%d:%d.%d not found"), + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, scsihostsrc->unit); + } break; } default: diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index a3f1025..041ce65 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -825,6 +825,12 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr, if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) return 0; + /* Like AppArmorRestoreSecurityImageLabel() for a networked disk, + * do nothing for an iSCSI hostdev + */ + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + return 0; + if (profile_loaded(secdef->imagelabel) < 0) return 0; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 08f5041..0f92194 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -477,6 +477,12 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr, if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) return 0; + /* Like virSecurityDACSetSecurityImageLabel() for a networked disk, + * do nothing for an iSCSI hostdev + */ + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + return 0; + cbdata.manager = mgr; cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME); @@ -605,6 +611,12 @@ virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr, if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) return 0; + /* Like virSecurityDACRestoreSecurityImageLabelInt() for a networked disk, + * do nothing for an iSCSI hostdev + */ + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + return 0; + switch ((virDomainHostdevSubsysType) dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { virUSBDevicePtr usb; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index f32816f..c078cab 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1324,6 +1324,12 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def, virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; int ret = -1; + /* Like virSecuritySELinuxSetSecurityImageLabelInternal() for a networked + * disk, do nothing for an iSCSI hostdev + */ + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + return 0; + switch (dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { virUSBDevicePtr usb; @@ -1511,6 +1517,12 @@ virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr, virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; int ret = -1; + /* Like virSecuritySELinuxRestoreSecurityImageLabelInt() for a networked + * disk, do nothing for an iSCSI hostdev + */ + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + return 0; + switch (dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { virUSBDevicePtr usb; diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 83f85aa..53da626 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -920,6 +920,43 @@ virHostdevUpdateActiveUSBDevices(virHostdevManagerPtr mgr, return ret; } +static int +virHostdevUpdateActiveSCSIHostDevices(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr hostdev, + virDomainHostdevSubsysSCSIPtr scsisrc, + const char *drv_name, + const char *dom_name) +{ + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; + virSCSIDevicePtr scsi = NULL; + virSCSIDevicePtr tmp = NULL; + int ret = -1; + + if (!(scsi = virSCSIDeviceNew(NULL, + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, scsihostsrc->unit, + hostdev->readonly, hostdev->shareable))) + goto cleanup; + + if ((tmp = virSCSIDeviceListFind(mgr->activeSCSIHostdevs, scsi))) { + if (virSCSIDeviceSetUsedBy(tmp, drv_name, dom_name) < 0) { + virSCSIDeviceFree(scsi); + goto cleanup; + } + virSCSIDeviceFree(scsi); + } else { + if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0 || + virSCSIDeviceListAdd(mgr->activeSCSIHostdevs, scsi) < 0) { + virSCSIDeviceFree(scsi); + goto cleanup; + } + } + ret = 0; + + cleanup: + return ret; +} + int virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr, virDomainHostdevDefPtr *hostdevs, @@ -930,40 +967,26 @@ virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr, virDomainHostdevDefPtr hostdev = NULL; size_t i; int ret = -1; - virSCSIDevicePtr scsi = NULL; - virSCSIDevicePtr tmp = NULL; if (!nhostdevs) return 0; virObjectLock(mgr->activeSCSIHostdevs); for (i = 0; i < nhostdevs; i++) { - virDomainHostdevSubsysSCSIHostPtr scsihostsrc; + virDomainHostdevSubsysSCSIPtr scsisrc; hostdev = hostdevs[i]; - scsihostsrc = &hostdev->source.subsys.u.scsi.u.host; + scsisrc = &hostdev->source.subsys.u.scsi; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) continue; - if (!(scsi = virSCSIDeviceNew(NULL, - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit, - hostdev->readonly, hostdev->shareable))) - goto cleanup; - - if ((tmp = virSCSIDeviceListFind(mgr->activeSCSIHostdevs, scsi))) { - if (virSCSIDeviceSetUsedBy(tmp, drv_name, dom_name) < 0) { - virSCSIDeviceFree(scsi); - goto cleanup; - } - virSCSIDeviceFree(scsi); + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + continue; /* Not supported for iSCSI */ } else { - if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0 || - virSCSIDeviceListAdd(mgr->activeSCSIHostdevs, scsi) < 0) { - virSCSIDeviceFree(scsi); + if (virHostdevUpdateActiveSCSIHostDevices(mgr, hostdev, scsisrc, + drv_name, dom_name) < 0) goto cleanup; - } } } ret = 0; @@ -1193,6 +1216,38 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, return ret; } +static int +virHostdevPrepareSCSIHostDevices(virDomainHostdevDefPtr hostdev, + virDomainHostdevSubsysSCSIPtr scsisrc, + virSCSIDeviceListPtr list) +{ + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; + virSCSIDevicePtr scsi; + int ret = -1; + + if (hostdev->managed) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("SCSI host device doesn't support managed mode")); + goto cleanup; + } + + if (!(scsi = virSCSIDeviceNew(NULL, + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, scsihostsrc->unit, + hostdev->readonly, hostdev->shareable))) + goto cleanup; + + if (virSCSIDeviceListAdd(list, scsi) < 0) { + virSCSIDeviceFree(scsi); + goto cleanup; + } + + ret = 0; + + cleanup: + return ret; +} + int virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, @@ -1219,29 +1274,17 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, /* Loop 1: build temporary list */ for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; - virDomainHostdevSubsysSCSIHostPtr scsihostsrc = - &hostdev->source.subsys.u.scsi.u.host; - virSCSIDevicePtr scsi; + virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) continue; - if (hostdev->managed) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("SCSI host device doesn't support managed mode")); - goto cleanup; - } - - if (!(scsi = virSCSIDeviceNew(NULL, - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit, - hostdev->readonly, hostdev->shareable))) - goto cleanup; - - if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) { - virSCSIDeviceFree(scsi); - goto cleanup; + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + continue; /* Not supported for iSCSI */ + } else { + if (virHostdevPrepareSCSIHostDevices(hostdev, scsisrc, list) < 0) + goto cleanup; } } @@ -1366,6 +1409,48 @@ virHostdevReAttachUSBDevices(virHostdevManagerPtr hostdev_mgr, virObjectUnlock(hostdev_mgr->activeUSBHostdevs); } +static void +virHostdevReAttachSCSIHostDevices(virHostdevManagerPtr hostdev_mgr, + virDomainHostdevDefPtr hostdev, + virDomainHostdevSubsysSCSIPtr scsisrc, + const char *drv_name, + const char *dom_name) +{ + virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; + virSCSIDevicePtr scsi; + virSCSIDevicePtr tmp; + + if (!(scsi = virSCSIDeviceNew(NULL, + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, scsihostsrc->unit, + hostdev->readonly, hostdev->shareable))) { + VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s", + scsihostsrc->adapter, scsihostsrc->bus, scsihostsrc->target, + scsihostsrc->unit, dom_name); + return; + } + + /* Only delete the devices which are marked as being used by @name, + * because qemuProcessStart could fail on the half way. */ + + if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeSCSIHostdevs, scsi))) { + VIR_WARN("Unable to find device %s:%d:%d:%d " + "in list of active SCSI devices", + scsihostsrc->adapter, scsihostsrc->bus, + scsihostsrc->target, scsihostsrc->unit); + virSCSIDeviceFree(scsi); + return; + } + + VIR_DEBUG("Removing %s:%d:%d:%d dom=%s from activeSCSIHostdevs", + scsihostsrc->adapter, scsihostsrc->bus, scsihostsrc->target, + scsihostsrc->unit, dom_name); + + virSCSIDeviceListDel(hostdev_mgr->activeSCSIHostdevs, tmp, + drv_name, dom_name); + virSCSIDeviceFree(scsi); +} + void virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, @@ -1381,44 +1466,17 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr, virObjectLock(hostdev_mgr->activeSCSIHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; - virDomainHostdevSubsysSCSIHostPtr scsihostsrc = - &hostdev->source.subsys.u.scsi.u.host; - virSCSIDevicePtr scsi; - virSCSIDevicePtr tmp; + virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) continue; - if (!(scsi = virSCSIDeviceNew(NULL, - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit, - hostdev->readonly, hostdev->shareable))) { - VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s", - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit, dom_name); - continue; - } - - /* Only delete the devices which are marked as being used by @name, - * because qemuProcessStart could fail on the half way. */ - - if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeSCSIHostdevs, scsi))) { - VIR_WARN("Unable to find device %s:%d:%d:%d " - "in list of active SCSI devices", - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit); - virSCSIDeviceFree(scsi); - continue; - } - - VIR_DEBUG("Removing %s:%d:%d:%d dom=%s from activeSCSIHostdevs", - scsihostsrc->adapter, scsihostsrc->bus, - scsihostsrc->target, scsihostsrc->unit, dom_name); - - virSCSIDeviceListDel(hostdev_mgr->activeSCSIHostdevs, tmp, - drv_name, dom_name); - virSCSIDeviceFree(scsi); + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) + continue; /* Not supported for iSCSI */ + else + virHostdevReAttachSCSIHostDevices(hostdev_mgr, hostdev, scsisrc, + drv_name, dom_name); } virObjectUnlock(hostdev_mgr->activeSCSIHostdevs); } -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list