[libvirt] [PATCH 09/12] Specify bus/unit instead of index for disks with QEMU

Daniel P. Berrange berrange at redhat.com
Thu Dec 10 22:22:29 UTC 2009


The current code for using -drive simply sets the -drive 'index'
parameter. QEMU internally converts this to bus/unit depending
on the type of drive. This does not give us precise control over
the bus/unit assignment though. This change switches over to make
libvirt explicitly calculate the bus/unit number.

In addition bus/unit/index are actually irrelevant for VirtIO
disks, since each virtio disk is a separate PCI device. No disk
controller is involved.

Doing the conversion to bus/unit in libvirt allows us to correctly
attach SCSI controllers when required.

* src/qemu/qemu_conf.c: Specify bus/unit instead of index for
  disks
---
 src/qemu/qemu_conf.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 79 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 27faa3f..f4fbe96 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1342,6 +1342,7 @@ qemuBuildDriveStr(virConnectPtr conn,
     const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
     int idx = virDiskNameToIndex(disk->dst);
     char *optstr = NULL;
+    int controllerid = -1, busid = -1, unitid = -1;
 
     if (idx < 0) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1349,6 +1350,80 @@ qemuBuildDriveStr(virConnectPtr conn,
         goto error;
     }
 
+    switch (disk->bus) {
+    case VIR_DOMAIN_DISK_BUS_SCSI:
+    case VIR_DOMAIN_DISK_BUS_IDE:
+    case VIR_DOMAIN_DISK_BUS_FDC:
+        if (disk->addr.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE &&
+            disk->addr.mode == VIR_DOMAIN_DEVICE_ADDRESS_MODE_STATIC) {
+            /* The user specified an explicit address, so ignore dev name */
+            controllerid = disk->addr.data.drive.controller;
+            busid = disk->addr.data.drive.bus;
+            unitid = disk->addr.data.drive.unit;
+        } else if (disk->addr.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
+                   disk->addr.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
+            /*
+             * We auto-assign contoller/bus/unit based on the drive
+             * index, which was in turn based on dev name eg "sda"
+             */
+            if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
+                /* Many SCSI controllers, only 1 bus, each with 7 units */
+                controllerid = idx / 7;
+                busid = 0;
+                unitid = idx % 7;
+            } else if (disk->bus == VIR_DOMAIN_DISK_BUS_IDE) {
+                /* One IDE controller, with 2 buses, each 2 units */
+                controllerid = 0;
+                busid = idx / 2;
+                unitid = idx % 2;
+            } else {
+                controllerid = 0;
+                busid = 0;
+                unitid = idx;
+            }
+
+            disk->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+            disk->addr.mode = VIR_DOMAIN_DEVICE_ADDRESS_MODE_DYNAMIC;
+            disk->addr.data.drive.controller = controllerid;
+            disk->addr.data.drive.bus = busid;
+            disk->addr.data.drive.unit = unitid;
+        } else {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
+                             _("unexpected address type for ide/scsi/fdc disk"));
+            goto error;
+        }
+        break;
+
+    case VIR_DOMAIN_DISK_BUS_VIRTIO:
+        /* Each virtio drive is a separate PCI device, no unit/busid */
+        break;
+
+    case VIR_DOMAIN_DISK_BUS_XEN:
+        /* Xen has no address type currently, so assign based on index */
+        unitid = idx;
+        break;
+    }
+
+    if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
+        if (busid != 0) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                             _("SCSI controller only supports 1 bus"));
+            goto error;
+        }
+        /* Setting bus= attr for SCSI drives, causes a controller
+         * to be created. Yes this is slightly odd. It is not possible
+         * to have > 1 bus on a SCSI controller (yet). */
+        busid = controllerid;
+    } else if (disk->bus == VIR_DOMAIN_DISK_BUS_IDE ||
+               disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
+        /* We can only have 1 IDE / Floppy controller (currently) */
+        if (controllerid != 0) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                             _("Only 1 %s controller is supported"), bus);
+            goto error;
+        }
+    }
+
     if (disk->src) {
         if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
             /* QEMU only supports magic FAT format for now */
@@ -1375,7 +1450,10 @@ qemuBuildDriveStr(virConnectPtr conn,
     virBufferVSprintf(&opt, "if=%s", bus);
     if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
         virBufferAddLit(&opt, ",media=cdrom");
-    virBufferVSprintf(&opt, ",index=%d", idx);
+    if (busid != -1)
+        virBufferVSprintf(&opt, ",bus=%d", busid);
+    if (unitid != -1)
+        virBufferVSprintf(&opt, ",unit=%d", unitid);
     if (bootable &&
         disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
         virBufferAddLit(&opt, ",boot=on");
-- 
1.6.5.2




More information about the libvir-list mailing list