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(a)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