From: Matthias Dahl <mdvirt(a)designassembly.de>
qemu allows the user to choose what io storage api should be used, either the
default (threads) or native (linux aio) which in the latter case can result in
better performance.
Thanks a lot to Eric Blake and Matthias Bolte for their comments.
Red Hat Bugzilla #591703
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
I've rebased Matthias' patch against the latest git, and discovered
a bug in qemu_conf in the process (separate patch sent for that).
I also discovered that formatdomain.html.in is incomplete; it lacks
mention of at least the recent error_policy option. But I ran out
of time to make a separate patch to bring it all up to date tonight.
docs/formatdomain.html.in | 5 ++++-
docs/schemas/domain.rng | 11 +++++++++++
src/conf/domain_conf.c | 23 +++++++++++++++++++++++
src/conf/domain_conf.h | 10 ++++++++++
src/qemu/qemu_conf.c | 15 ++++++++++++++-
src/qemu/qemu_conf.h | 1 +
tests/qemuhelptest.c | 6 ++++--
7 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a23663a..5c178d8 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -520,7 +520,10 @@
attribute is the primary backend driver name, while the optional
<code>type</code>
attribute provides the sub-type. The optional <code>cache</code>
attribute
controls the cache mechanism, possible values are "default",
"none",
- "writethrough" and "writeback". <span
class="since">Since 0.1.8</span>
+ "writethrough" and "writeback". Specific to KVM guests is the
optional <code>aio</code>
+ attribute which controls what storage api is used for io operations, its
possible
+ values are "threads" and "native". <span
class="since">Since
+ 0.1.8; <code>aio</code> attribute since 0.8.2</span>
</dd>
<dt><code>encryption</code></dt>
<dd>If present, specifies how the volume is encrypted. See
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 56b6705..acbbf9f 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -602,6 +602,9 @@
<optional>
<ref name="driverErrorPolicy"/>
</optional>
+ <optional>
+ <ref name="driverAIO"/>
+ </optional>
<empty/>
</element>
</define>
@@ -633,6 +636,14 @@
</choice>
</attribute>
</define>
+ <define name="driverAIO">
+ <attribute name="aio">
+ <choice>
+ <value>threads</value>
+ <value>native</value>
+ </choice>
+ </attribute>
+ </define>
<define name="controller">
<element name="controller">
<choice>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3e45f79..118585a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -132,6 +132,11 @@ VIR_ENUM_IMPL(virDomainDiskErrorPolicy,
VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
"ignore",
"enospace")
+VIR_ENUM_IMPL(virDomainDiskAIO, VIR_DOMAIN_DISK_AIO_LAST,
+ "default",
+ "native",
+ "threads")
+
VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
"ide",
"fdc",
@@ -1378,6 +1383,7 @@ virDomainDiskDefParseXML(xmlNodePtr node,
char *bus = NULL;
char *cachetag = NULL;
char *error_policy = NULL;
+ char *aiotag = NULL;
char *devaddr = NULL;
virStorageEncryptionPtr encryption = NULL;
char *serial = NULL;
@@ -1444,6 +1450,7 @@ virDomainDiskDefParseXML(xmlNodePtr node,
driverType = virXMLPropString(cur, "type");
cachetag = virXMLPropString(cur, "cache");
error_policy = virXMLPropString(cur, "error_policy");
+ aiotag = virXMLPropString(cur, "aio");
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
def->readonly = 1;
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
@@ -1567,6 +1574,13 @@ virDomainDiskDefParseXML(xmlNodePtr node,
goto error;
}
+ if (aiotag &&
+ (def->aiomode = virDomainDiskAIOTypeFromString(aiotag)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown disk aio mode '%s'"), aiotag);
+ goto error;
+ }
+
if (devaddr) {
if (virDomainParseLegacyDeviceAddress(devaddr,
&def->info.addr.pci) < 0) {
@@ -1608,6 +1622,7 @@ cleanup:
VIR_FREE(driverName);
VIR_FREE(cachetag);
VIR_FREE(error_policy);
+ VIR_FREE(aiotag);
VIR_FREE(devaddr);
VIR_FREE(serial);
virStorageEncryptionFree(encryption);
@@ -4887,6 +4902,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
const char *bus = virDomainDiskBusTypeToString(def->bus);
const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode);
const char *error_policy =
virDomainDiskErrorPolicyTypeToString(def->error_policy);
+ const char *aiomode = virDomainDiskAIOTypeToString(def->aiomode);
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4908,6 +4924,11 @@ virDomainDiskDefFormat(virBufferPtr buf,
_("unexpected disk cache mode %d"),
def->cachemode);
return -1;
}
+ if (!aiomode) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected disk aio mode %d"),
def->aiomode);
+ return -1;
+ }
virBufferVSprintf(buf,
" <disk type='%s'
device='%s'>\n",
@@ -4923,6 +4944,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferVSprintf(buf, " cache='%s'", cachemode);
if (def->error_policy)
virBufferVSprintf(buf, " error_policy='%s'",
error_policy);
+ if (def->aiomode)
+ virBufferVSprintf(buf, " aio='%s'", aiomode);
virBufferVSprintf(buf, "/>\n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fadc8bd..1eec1d2 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -161,6 +161,14 @@ enum virDomainDiskErrorPolicy {
VIR_DOMAIN_DISK_ERROR_POLICY_LAST
};
+enum virDomainDiskAIO {
+ VIR_DOMAIN_DISK_AIO_DEFAULT,
+ VIR_DOMAIN_DISK_AIO_NATIVE,
+ VIR_DOMAIN_DISK_AIO_THREADS,
+
+ VIR_DOMAIN_DISK_AIO_LAST
+};
+
/* Stores the virtual disk configuration */
typedef struct _virDomainDiskDef virDomainDiskDef;
typedef virDomainDiskDef *virDomainDiskDefPtr;
@@ -175,6 +183,7 @@ struct _virDomainDiskDef {
char *serial;
int cachemode;
int error_policy;
+ int aiomode;
unsigned int readonly : 1;
unsigned int shared : 1;
virDomainDeviceInfo info;
@@ -1069,6 +1078,7 @@ VIR_ENUM_DECL(virDomainDiskDevice)
VIR_ENUM_DECL(virDomainDiskBus)
VIR_ENUM_DECL(virDomainDiskCache)
VIR_ENUM_DECL(virDomainDiskErrorPolicy)
+VIR_ENUM_DECL(virDomainDiskAIO)
VIR_ENUM_DECL(virDomainController)
VIR_ENUM_DECL(virDomainFS)
VIR_ENUM_DECL(virDomainNet)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 5fa8c0a..87998c1 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1,7 +1,7 @@
/*
* qemu_conf.c: QEMU configuration management
*
- * Copyright (C) 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
+ * Copyright (C) 2006-2010 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -85,6 +85,12 @@ VIR_ENUM_IMPL(qemuDiskCacheV2, VIR_DOMAIN_DISK_CACHE_LAST,
"writethrough",
"writeback");
+VIR_ENUM_DECL(qemuDiskAIO)
+VIR_ENUM_IMPL(qemuDiskAIO, VIR_DOMAIN_DISK_AIO_LAST,
+ "default",
+ "native",
+ "threads");
+
VIR_ENUM_DECL(qemuVideo)
VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
@@ -1150,6 +1156,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
flags |= QEMUD_CMD_FLAG_DRIVE_CACHE_V2;
if (strstr(help, "format="))
flags |= QEMUD_CMD_FLAG_DRIVE_FORMAT;
+ if (strstr(help, "aio=threads|native"))
+ flags |= QEMUD_CMD_FLAG_DRIVE_AIO;
}
if (strstr(help, "-vga") && !strstr(help, "-std-vga"))
flags |= QEMUD_CMD_FLAG_VGA;
@@ -2518,6 +2526,11 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
}
}
+ if (disk->aiomode && (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_AIO)) {
+ virBufferVSprintf(&opt, ",aio=%s",
+ qemuDiskAIOTypeToString(disk->aiomode));
+ }
+
if (virBufferError(&opt)) {
virReportOOMError();
goto error;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index a101e47..44043b4 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -88,6 +88,7 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_NO_HPET = (1LL << 33), /* -no-hpet flag is supported */
QEMUD_CMD_FLAG_NO_KVM_PIT = (1LL << 34), /* -no-kvm-pit-reinjection
supported */
QEMUD_CMD_FLAG_TDF = (1LL << 35), /* -tdf flag (user-mode pit
catchup) */
+ QEMUD_CMD_FLAG_DRIVE_AIO = (1LL << 36), /* -drive aio= supported */
};
/* Main driver state */
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index 517a8fe..a00c743 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -244,7 +244,8 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_SMP_TOPOLOGY |
QEMUD_CMD_FLAG_RTC |
- QEMUD_CMD_FLAG_NO_HPET,
+ QEMUD_CMD_FLAG_NO_HPET |
+ QEMUD_CMD_FLAG_DRIVE_AIO,
12001, 0, 0);
DO_TEST("qemu-kvm-0.12.3",
QEMUD_CMD_FLAG_VNC_COLON |
@@ -274,7 +275,8 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_VNET_HOST |
QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT |
- QEMUD_CMD_FLAG_TDF,
+ QEMUD_CMD_FLAG_TDF |
+ QEMUD_CMD_FLAG_DRIVE_AIO,
12003, 1, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
--
1.7.0.1