[libvirt] [PATCH 6/8] hostdev: Introduce virDomainHostdevSubsysSCSIiSCSI

John Ferlan jferlan at redhat.com
Fri Jul 11 12:35:35 UTC 2014


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 at redhat.com>
---
 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 55c0822..758b907 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1702,6 +1702,17 @@ virDomainHostdevDefPtr virDomainHostdevDefAlloc(void)
     return def;
 }
 
+static void
+virDomainHostdevSubsysSCSIiSCSIFree(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)
@@ -1732,8 +1743,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) {
+                virDomainHostdevSubsysSCSIiSCSIFree(&scsisrc->u.iscsi);
+            } else {
+                VIR_FREE(scsisrc->u.host.adapter);
+            }
+        }
         break;
     }
 }
@@ -4313,8 +4331,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;
@@ -10161,6 +10178,22 @@ virDomainHostdevMatchSubsysSCSIHost(virDomainHostdevDefPtr a,
 }
 
 static int
+virDomainHostdevMatchSubsysSCSIiSCSI(virDomainHostdevDefPtr a,
+                                     virDomainHostdevDefPtr b)
+{
+    virDomainHostdevSubsysSCSIiSCSIPtr aiscsisrc =
+        &a->source.subsys.u.scsi.u.iscsi;
+    virDomainHostdevSubsysSCSIiSCSIPtr biscsisrc =
+        &b->source.subsys.u.scsi.u.iscsi;
+
+    if (STREQ(aiscsisrc->hosts[0].name, biscsisrc->hosts[0].name) &&
+        STREQ(aiscsisrc->hosts[0].port, biscsisrc->hosts[0].port) &&
+        STREQ(aiscsisrc->path, biscsisrc->path))
+        return 1;
+    return 0;
+}
+
+static int
 virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
                             virDomainHostdevDefPtr b)
 {
@@ -10173,7 +10206,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 e9a4214..e6aa1db 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -390,6 +390,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 {
@@ -418,12 +427,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 9a5459b..e109c33 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 1ab3ade..4a2a5ea 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5119,13 +5119,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;
@@ -5135,10 +5133,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);
@@ -5157,10 +5209,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 40c667e..af9de2d 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -814,6 +814,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




More information about the libvir-list mailing list