The domain XML parsing code autogenerates disk address and
controller elements when they are not explicitly specified.
The code assumes a narrow SCSI bus (7 units per bus). ESX
uses a wide SCSI bus (16 units per bus).

This is a step towards controller support for the ESX driver.
---
 src/conf/capabilities.h |    3 +++
 src/conf/domain_conf.c  |   39 +++++++++++++++++++++++++++++----------
 src/conf/domain_conf.h  |    2 +-
 src/esx/esx_driver.c    |    2 ++
 src/qemu/qemu_conf.c    |    9 +++++----
 5 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index bdf44fa..9290c82 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -24,6 +24,8 @@
 #ifndef __VIR_CAPABILITIES_H
 # define __VIR_CAPABILITIES_H
 
+# include <stdbool.h>
+
 # include "internal.h"
 # include "util.h"
 # include "buf.h"
@@ -125,6 +127,7 @@ struct _virCaps {
     void (*privateDataFreeFunc)(void *);
     int (*privateDataXMLFormat)(virBufferPtr, void *);
     int (*privateDataXMLParse)(xmlXPathContextPtr, void *);
+    bool hasWideScsiBus;
 };
 
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 64b5cf3..cac4042 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1339,7 +1339,7 @@ virDomainParseLegacyDeviceAddress(char *devaddr,
 }
 
 int
-virDomainDiskDefAssignAddress(virDomainDiskDefPtr def)
+virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
 {
     int idx = virDiskNameToIndex(def->dst);
     if (idx < 0)
@@ -1347,12 +1347,30 @@ virDomainDiskDefAssignAddress(virDomainDiskDefPtr def)
 
     switch (def->bus) {
     case VIR_DOMAIN_DISK_BUS_SCSI:
-        /* For SCSI we define the default mapping to be 7 units
-         * per bus, 1 bus per controller, many controllers */
         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
-        def->info.addr.drive.controller = idx / 7;
-        def->info.addr.drive.bus = 0;
-        def->info.addr.drive.unit = idx % 7;
+
+        if (caps->hasWideScsiBus) {
+            /* For a wide SCSI bus we define the default mapping to be
+             * 16 units per bus, 1 bus per controller, many controllers.
+             * Unit 7 is the SCSI controller itself. Therefore unit 7
+             * cannot be assigned to disks and is skipped.
+             */
+            def->info.addr.drive.controller = idx / 15;
+            def->info.addr.drive.bus = 0;
+            def->info.addr.drive.unit = idx % 15;
+
+            /* Skip the SCSI controller at unit 7 */
+            if (def->info.addr.drive.unit >= 7) {
+                ++def->info.addr.drive.unit;
+            }
+        } else {
+            /* For a narrow SCSI bus we define the default mapping to be
+             * 7 units per bus, 1 bus per controller, many controllers */
+            def->info.addr.drive.controller = idx / 7;
+            def->info.addr.drive.bus = 0;
+            def->info.addr.drive.unit = idx % 7;
+        }
+
         break;
 
     case VIR_DOMAIN_DISK_BUS_IDE:
@@ -1385,7 +1403,8 @@ virDomainDiskDefAssignAddress(virDomainDiskDefPtr def)
  * @param node XML nodeset to parse for disk definition
  */
 static virDomainDiskDefPtr
-virDomainDiskDefParseXML(xmlNodePtr node,
+virDomainDiskDefParseXML(virCapsPtr caps,
+                         xmlNodePtr node,
                          int flags) {
     virDomainDiskDefPtr def;
     xmlNodePtr cur;
@@ -1615,7 +1634,7 @@ virDomainDiskDefParseXML(xmlNodePtr node,
     serial = NULL;
 
     if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
-        && virDomainDiskDefAssignAddress(def) < 0)
+        && virDomainDiskDefAssignAddress(caps, def) < 0)
         goto error;
 
 cleanup:
@@ -3687,7 +3706,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr 
caps,
 
     if (xmlStrEqual(node->name, BAD_CAST "disk")) {
         dev->type = VIR_DOMAIN_DEVICE_DISK;
-        if (!(dev->data.disk = virDomainDiskDefParseXML(node, flags)))
+        if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, flags)))
             goto error;
     } else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
         dev->type = VIR_DOMAIN_DEVICE_FS;
@@ -4237,7 +4256,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr 
caps,
     if (n && VIR_ALLOC_N(def->disks, n) < 0)
         goto no_memory;
     for (i = 0 ; i < n ; i++) {
-        virDomainDiskDefPtr disk = virDomainDiskDefParseXML(nodes[i],
+        virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps, nodes[i],
                                                             flags);
         if (!disk)
             goto error;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f83de83..701849f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -999,7 +999,7 @@ int virDomainDiskInsert(virDomainDefPtr def,
                         virDomainDiskDefPtr disk);
 void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
                                    virDomainDiskDefPtr disk);
-int virDomainDiskDefAssignAddress(virDomainDiskDefPtr def);
+int virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def);
 
 int virDomainControllerInsert(virDomainDefPtr def,
                               virDomainControllerDefPtr controller);
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 1968537..f50e090 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -228,6 +228,8 @@ esxCapsInit(esxPrivate *priv)
     virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 });
     virCapabilitiesAddHostMigrateTransport(caps, "esx");
 
+    caps->hasWideScsiBus = true;
+
     if (esxLookupHostSystemBiosUuid(priv, caps->host.host_uuid) < 0) {
         goto failure;
     }
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index f096876..1b18a5f 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -5019,7 +5019,8 @@ error:
  * Will fail if not using the 'index' keyword
  */
 static virDomainDiskDefPtr
-qemuParseCommandLineDisk(const char *val,
+qemuParseCommandLineDisk(virCapsPtr caps,
+                         const char *val,
                          int nvirtiodisk)
 {
     virDomainDiskDefPtr def = NULL;
@@ -5192,7 +5193,7 @@ qemuParseCommandLineDisk(const char *val,
     else
         def->dst[2] = 'a' + idx;
 
-    if (virDomainDiskDefAssignAddress(def) < 0) {
+    if (virDomainDiskDefAssignAddress(caps, def) < 0) {
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
                         _("invalid device name '%s'"), def->dst);
         virDomainDiskDefFree(def);
@@ -6004,7 +6005,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
                 goto no_memory;
             }
 
-            if (virDomainDiskDefAssignAddress(disk) < 0)
+            if (virDomainDiskDefAssignAddress(caps, disk) < 0)
                 goto error;
 
             if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
@@ -6152,7 +6153,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
         } else if (STREQ(arg, "-drive")) {
             virDomainDiskDefPtr disk;
             WANT_VALUE();
-            if (!(disk = qemuParseCommandLineDisk(val, nvirtiodisk)))
+            if (!(disk = qemuParseCommandLineDisk(caps, val, nvirtiodisk)))
                 goto error;
             if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
                 virDomainDiskDefFree(disk);
-- 
1.7.0.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to