[libvirt] [PATCH 1/2] conf: Support for Block Device IO Limits

Viktor Mihajlovski mihajlov at linux.vnet.ibm.com
Wed Aug 29 15:48:30 UTC 2012


Introducing a new iolimits element allowing to override certain
properties of a guest block device like the physical and logical
block size.
This can be useful for platforms with 'non-standard' disk formats
like S390 DASD with its 4K block size.

Signed-off-by: Viktor Mihajlovski <mihajlov at linux.vnet.ibm.com>
---
 docs/formatdomain.html.in     |   18 +++++++++++++++
 docs/schemas/domaincommon.rng |   17 ++++++++++++++
 src/conf/domain_conf.c        |   49 +++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h        |    5 ++++
 4 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index be8489a..db77cc4 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1264,6 +1264,7 @@
       <driver name='qemu' type='raw'/>
       <source dev='/dev/sda'/>
       <geometry cyls='16383' heads='16' secs='63' trans='lba'/>
+      <iolimits logical_block_size='512' physical_block_size='4096'/>
       <target dev='hda' bus='ide'/>
     </disk>
   </devices>
@@ -1632,6 +1633,23 @@
             BIOS-Translation-Modus (none, lba or auto)</dd>
         </dl>
       </dd>
+      <dt><code>iolimits</code></dt>
+      <dd>If present, the <code>iolimits</code> element allows
+        to override any of the block device properties listed below.
+        <span class="since">Since 0.10.1 (QEMU and KVM)</span>
+        <dl>
+          <dt><code>logical_block_size</code></dt>
+          <dd>The logical block size the disk will report to the guest
+            OS. For Linux this would be the value returned by the
+            BLKSSZGET ioctl and describes the smallest units for disk
+            I/O.
+          <dt><code>physical_block_size</code></dt>
+          <dd>The physical block size the disk will report to the guest
+            OS. For Linux this would be the value returned by the
+            BLKPBSZGET ioctl and describes the disk's hardware sector
+            size which can be relevant for the alignment of disk data.
+        </dl>
+      </dd>
     </dl>
 
     <h4><a name="elementsFilesystems">Filesystems</a></h4>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 145caf7..60cf33e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -886,6 +886,9 @@
       <optional>
         <ref name="geometry"/>
       </optional>
+      <optional>
+        <ref name="diskIoLimits"/>
+      </optional>
     </interleave>
   </define>
   <define name="snapshot">
@@ -1110,6 +1113,20 @@
       </optional>
     </element>
   </define>
+  <define name="diskIoLimits">
+    <element name="iolimits">
+      <optional>
+        <attribute name="logical_block_size">
+          <data type="integer"/>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="physical_block_size">
+          <data type="integer"/>
+        </attribute>
+      </optional>
+    </element>
+  </define>
   <!--
       Disk may use a special driver for access.
     -->
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 224aec5..0fb0bc4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3398,6 +3398,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     char *authUUID = NULL;
     char *usageType = NULL;
     char *tray = NULL;
+    char *logical_block_size = NULL;
+    char *physical_block_size = NULL;
 
     if (VIR_ALLOC(def) < 0) {
         virReportOOMError();
@@ -3409,6 +3411,9 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     def->geometry.sectors = 0;
     def->geometry.trans = VIR_DOMAIN_DISK_TRANS_DEFAULT;
 
+    def->iolimits.logical_block_size = 0;
+    def->iolimits.physical_block_size = 0;
+
     ctxt->node = node;
 
     type = virXMLPropString(node, "type");
@@ -3547,6 +3552,27 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                         goto error;
                     }
                 }
+            } else if (xmlStrEqual(cur->name, BAD_CAST "iolimits")) {
+                logical_block_size =
+                    virXMLPropString(cur, "logical_block_size");
+                if (logical_block_size &&
+                    virStrToLong_ui(logical_block_size, NULL, 0,
+                                    &def->iolimits.logical_block_size) < 0) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("invalid logical block size '%s'"),
+                                   logical_block_size);
+                    goto error;
+                }
+                physical_block_size =
+                    virXMLPropString(cur, "physical_block_size");
+                if (physical_block_size &&
+                    virStrToLong_ui(physical_block_size, NULL, 0,
+                                    &def->iolimits.physical_block_size) < 0) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("invalid physical block size '%s'"),
+                                   physical_block_size);
+                    goto error;
+                }
             } else if (!driverName &&
                        xmlStrEqual(cur->name, BAD_CAST "driver")) {
                 driverName = virXMLPropString(cur, "name");
@@ -4052,6 +4078,8 @@ cleanup:
     VIR_FREE(serial);
     virStorageEncryptionFree(encryption);
     VIR_FREE(startupPolicy);
+    VIR_FREE(logical_block_size);
+    VIR_FREE(physical_block_size);
 
     ctxt->node = save_ctxt;
     return def;
@@ -11312,6 +11340,26 @@ static void virDomainDiskGeometryDefFormat(virBufferPtr buf,
         virBufferAddLit(buf, "/>\n");
     }
 }
+static void virDomainDiskIolimitsDefFormat(virBufferPtr buf,
+                                           virDomainDiskDefPtr def)
+{
+    if (def->iolimits.logical_block_size > 0 ||
+        def->iolimits.physical_block_size > 0) {
+        virBufferAddLit(buf,"      <iolimits");
+        if (def->iolimits.logical_block_size > 0) {
+            virBufferAsprintf(buf,
+                              " logical_block_size='%u'",
+                              def->iolimits.logical_block_size);
+        }
+        if (def->iolimits.physical_block_size > 0) {
+            virBufferAsprintf(buf,
+                              " physical_block_size='%u'",
+                              def->iolimits.physical_block_size);
+        }
+        virBufferAddLit(buf, "/>\n");
+    }
+}
+
 
 static int
 virDomainDiskDefFormat(virBufferPtr buf,
@@ -11485,6 +11533,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
     }
 
     virDomainDiskGeometryDefFormat(buf, def);
+    virDomainDiskIolimitsDefFormat(buf, def);
 
     /* For now, mirroring is currently output-only: we only output it
      * for live domains, therefore we ignore it on input except for
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9ee57e1..35608bd 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -568,6 +568,11 @@ struct _virDomainDiskDef {
         int trans;
     } geometry;
 
+    struct {
+        unsigned int logical_block_size;
+        unsigned int physical_block_size;
+    } iolimits;
+
     virDomainBlockIoTuneInfo blkdeviotune;
 
     char *serial;
-- 
1.7.0.4




More information about the libvir-list mailing list