[libvirt] [PATCH 1/3] qemu: Support for Disk Geometry Override

Viktor Mihajlovski mihajlov at linux.vnet.ibm.com
Fri Jul 13 08:45:28 UTC 2012


From: J.B. Joret <jb at linux.vnet.ibm.com>

Qemu allows to override the disk geometry in the drive specification
with cyls=,heads=,secs=[,trans=].
This patch extends the domain config and the qemu driver to allow
the specification of disk geometry with libvirt.

Signed-off-by: J.B. Joret <jb at linux.vnet.ibm.com>
Signed-off-by: Viktor Mihajlovski <mihajlov at linux.vnet.ibm.com>
---
 src/conf/domain_conf.c   |   71 ++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |   17 +++++++++++
 src/libvirt_private.syms |    2 +
 src/qemu/qemu_command.c  |   59 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4f8c57a..4b208fc 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -170,6 +170,12 @@ VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
               "floppy",
               "lun")
 
+VIR_ENUM_IMPL(virDomainDiskGeometryTrans, VIR_DOMAIN_DISK_TRANS_LAST,
+              "default",
+              "none",
+              "auto",
+              "lba")
+
 VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
               "ide",
               "fdc",
@@ -3347,6 +3353,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     char *source = NULL;
     char *target = NULL;
     char *protocol = NULL;
+    char *trans = NULL;
     virDomainDiskHostDefPtr hosts = NULL;
     int nhosts = 0;
     char *bus = NULL;
@@ -3375,6 +3382,11 @@ virDomainDiskDefParseXML(virCapsPtr caps,
         return NULL;
     }
 
+    def->geometry.cylinders = 0;
+    def->geometry.heads = 0;
+    def->geometry.sectors = 0;
+    def->geometry.trans = VIR_DOMAIN_DISK_TRANS_DEFAULT;
+
     ctxt->node = node;
 
     type = virXMLPropString(node, "type");
@@ -3484,6 +3496,40 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                 if (target &&
                     STRPREFIX(target, "ioemu:"))
                     memmove(target, target+6, strlen(target)-5);
+            } else if (xmlStrEqual(cur->name, BAD_CAST "geometry")) {
+                if (virXPathUInt("string(./geometry/@cyls)",
+                                 ctxt, &def->geometry.cylinders) < 0) {
+                    virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                         _("invalid geometry settings (cyls)"));
+                    goto error;
+                }
+                if (virXPathUInt("string(./geometry/@heads)",
+                                 ctxt, &def->geometry.heads) < 0) {
+                    virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                         _("invalid geometry settings (heads)"));
+                    goto error;
+                }
+                if (virXPathUInt("string(./geometry/@secs)",
+                                 ctxt, &def->geometry.sectors) < 0) {
+                    virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                         _("invalid geometry settings (secs)"));
+                    goto error;
+                }
+                trans = virXMLPropString(cur, "trans");
+                if (trans != NULL) {
+                    if (STREQ(trans, "none"))
+                        def->geometry.trans = VIR_DOMAIN_DISK_TRANS_NONE;
+                    else if (STREQ(trans, "auto"))
+                        def->geometry.trans = VIR_DOMAIN_DISK_TRANS_AUTO;
+                    else if (STREQ(trans, "lba"))
+                        def->geometry.trans = VIR_DOMAIN_DISK_TRANS_LBA;
+                    else {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                             _("invalid translation value '%s'"),
+                                             trans);
+                        goto error;
+                    }
+                }
             } else if (!driverName &&
                        xmlStrEqual(cur->name, BAD_CAST "driver")) {
                 driverName = virXMLPropString(cur, "name");
@@ -3962,6 +4008,7 @@ cleanup:
     VIR_FREE(target);
     VIR_FREE(source);
     VIR_FREE(tray);
+    VIR_FREE(trans);
     while (nhosts > 0) {
         virDomainDiskHostDefFree(&hosts[nhosts - 1]);
         nhosts--;
@@ -10973,6 +11020,28 @@ virDomainLeaseDefFormat(virBufferPtr buf,
     return 0;
 }
 
+static void virDomainDiskGeometryDefFormat(virBufferPtr buf,
+                                           virDomainDiskDefPtr def)
+{
+    const char *trans =
+        virDomainDiskGeometryTransTypeToString(def->geometry.trans);
+
+    if (def->geometry.cylinders > 0 &&
+        def->geometry.heads > 0 &&
+        def->geometry.sectors > 0) {
+        virBufferAsprintf(buf,
+                          "      <geometry cyls='%u' heads='%u' secs='%u'",
+                          def->geometry.cylinders,
+                          def->geometry.heads,
+                          def->geometry.sectors);
+
+        if (def->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
+            virBufferEscapeString(buf, " trans='%s'", trans);
+
+        virBufferAddLit(buf, "/>\n");
+    }
+}
+
 static int
 virDomainDiskDefFormat(virBufferPtr buf,
                        virDomainDiskDefPtr def,
@@ -11094,6 +11163,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
             } else {
                 virBufferAddLit(buf, "/>\n");
             }
+            virDomainDiskGeometryDefFormat(buf, def);
             break;
         case VIR_DOMAIN_DISK_TYPE_BLOCK:
             virBufferEscapeString(buf, "      <source dev='%s'",
@@ -11107,6 +11177,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
             } else {
                 virBufferAddLit(buf, "/>\n");
             }
+            virDomainDiskGeometryDefFormat(buf, def);
             break;
         case VIR_DOMAIN_DISK_TYPE_DIR:
             virBufferEscapeString(buf, "      <source dir='%s'/>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5e5374a..018a1f1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -466,6 +466,15 @@ enum virDomainDiskTray {
     VIR_DOMAIN_DISK_TRAY_LAST
 };
 
+enum  virDomainDiskGeometryTrans {
+    VIR_DOMAIN_DISK_TRANS_DEFAULT = 0,
+    VIR_DOMAIN_DISK_TRANS_NONE,
+    VIR_DOMAIN_DISK_TRANS_AUTO,
+    VIR_DOMAIN_DISK_TRANS_LBA,
+
+    VIR_DOMAIN_DISK_TRANS_LAST
+};
+
 typedef struct _virDomainDiskHostDef virDomainDiskHostDef;
 typedef virDomainDiskHostDef *virDomainDiskHostDefPtr;
 struct _virDomainDiskHostDef {
@@ -575,6 +584,13 @@ struct _virDomainDiskDef {
     char *mirrorFormat;
     bool mirroring;
 
+    struct {
+        unsigned int cylinders;
+        unsigned int heads;
+        unsigned int sectors;
+        int trans;
+    } geometry;
+
     virDomainBlockIoTuneInfo blkdeviotune;
 
     char *serial;
@@ -2165,6 +2181,7 @@ VIR_ENUM_DECL(virDomainDeviceAddress)
 VIR_ENUM_DECL(virDomainDeviceAddressPciMulti)
 VIR_ENUM_DECL(virDomainDisk)
 VIR_ENUM_DECL(virDomainDiskDevice)
+VIR_ENUM_DECL(virDomainDiskGeometryTrans)
 VIR_ENUM_DECL(virDomainDiskBus)
 VIR_ENUM_DECL(virDomainDiskCache)
 VIR_ENUM_DECL(virDomainDiskErrorPolicy)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b173590..6b2064e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -304,6 +304,8 @@ virDomainDiskDefAssignAddress;
 virDomainDiskDefForeachPath;
 virDomainDiskDefFree;
 virDomainDiskDeviceTypeToString;
+virDomainDiskGeometryTransTypeToString;
+virDomainDiskGeometryTransTypeFromString;
 virDomainDiskErrorPolicyTypeFromString;
 virDomainDiskErrorPolicyTypeToString;
 virDomainDiskFindControllerModel;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ae48678..23d1aba 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2016,6 +2016,8 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
 {
     virBuffer opt = VIR_BUFFER_INITIALIZER;
     const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
+    const char *trans =
+        virDomainDiskGeometryTransTypeToString(disk->geometry.trans);
     int idx = virDiskNameToIndex(disk->dst);
     int busid = -1, unitid = -1;
 
@@ -2218,6 +2220,24 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
         disk->type != VIR_DOMAIN_DISK_TYPE_DIR &&
         qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT))
         virBufferAsprintf(&opt, ",format=%s", disk->driverType);
+
+    /* generate geometry command string*/
+    if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK ||
+        disk->type == VIR_DOMAIN_DISK_TYPE_FILE) {
+        if (disk->geometry.cylinders > 0 &&
+            disk->geometry.heads > 0 &&
+            disk->geometry.sectors > 0) {
+
+            virBufferAsprintf(&opt, ",cyls=%u,heads=%u,secs=%u",
+                              disk->geometry.cylinders,
+                              disk->geometry.heads,
+                              disk->geometry.sectors);
+
+            if (disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
+                virBufferEscapeString(&opt, ",trans=%s", trans);
+        }
+    }
+
     if (disk->serial &&
         qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_SERIAL)) {
         if (qemuSafeSerialParamValue(disk->serial) < 0)
@@ -6599,6 +6619,7 @@ qemuParseCommandLineDisk(virCapsPtr caps,
     int idx = -1;
     int busid = -1;
     int unitid = -1;
+    int trans = VIR_DOMAIN_DISK_TRANS_DEFAULT;
 
     if ((nkeywords = qemuParseKeywords(val,
                                        &keywords,
@@ -6803,6 +6824,44 @@ qemuParseCommandLineDisk(virCapsPtr caps,
                 qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("cannot parse io mode '%s'"), values[i]);
             }
+        } else if (STREQ(keywords[i], "cyls")) {
+            if (virStrToLong_ui(values[i], NULL, 10,
+                                &(def->geometry.cylinders)) < 0) {
+                virDomainDiskDefFree(def);
+                def = NULL;
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("cannot parse cylinders value'%s'"),
+                                values[i]);
+            }
+        } else if (STREQ(keywords[i], "heads")) {
+            if (virStrToLong_ui(values[i], NULL, 10,
+                                &(def->geometry.heads)) < 0) {
+                virDomainDiskDefFree(def);
+                def = NULL;
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("cannot parse heads value'%s'"),
+                                values[i]);
+            }
+        } else if (STREQ(keywords[i], "secs")) {
+            if (virStrToLong_ui(values[i], NULL, 10,
+                                &(def->geometry.sectors)) < 0) {
+                virDomainDiskDefFree(def);
+                def = NULL;
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("cannot parse sectors value'%s'"),
+                                values[i]);
+            }
+        } else if (STREQ(keywords[i], "trans")) {
+            def->geometry.trans =
+                virDomainDiskGeometryTransTypeFromString(values[i]);
+            if ((trans < VIR_DOMAIN_DISK_TRANS_DEFAULT) ||
+                (trans >= VIR_DOMAIN_DISK_TRANS_LAST)) {
+                virDomainDiskDefFree(def);
+                def = NULL;
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("cannot parse translation value'%s'"),
+                                values[i]);
+            }
         }
     }
 
-- 
1.7.0.4




More information about the libvir-list mailing list