This option allows or disallows detection of zero-writes if it is set to
"on" or "off", respectively. It can be also set to "unmap"
in which
case it will try discarding that part of image based on the value of the
"discard" option.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
docs/formatdomain.html.in | 10 +++++
docs/schemas/domaincommon.rng | 12 ++++++
src/conf/domain_conf.c | 23 ++++++++++-
src/conf/domain_conf.h | 11 ++++++
src/libvirt_private.syms | 2 +
.../qemuxml2argv-disk-drive-detect-zeroes.xml | 45 ++++++++++++++++++++++
.../qemuxml2xmlout-disk-drive-detect-zeroes.xml | 1 +
tests/qemuxml2xmltest.c | 1 +
8 files changed, 104 insertions(+), 1 deletion(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.xml
create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-detect-zeroes.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a524c173afbe..1a641561e76b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2499,6 +2499,16 @@
are numbered from 1 to the domain iothreads value.
<span class='since'>Since 1.2.8 (QEMU only)</span>
</li>
+ <li>
+ The optional <code>detect_zeroes</code> attribute controls
+ whether to detect zero write requests. The value can be "off",
+ "on" or "unmap". First two values turn the detection off
and
+ on, respectively, the third value turns the detection on and
+ tries to discard such areas from the image based on the value
+ of <code>discard</code> above (it will act as "on" if
+ <code>discard</code> is set to "ignore").
+ <span class='since'>Since 1.3.1 (QEMU and KVM
only)</span>
+ </li>
</ul>
</dd>
<dt><code>backenddomain</code></dt>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 67af93a004f0..07af64cba1ec 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1576,6 +1576,9 @@
<optional>
<ref name="driverIOThread"/>
</optional>
+ <optional>
+ <ref name="detect_zeroes"/>
+ </optional>
<empty/>
</element>
</define>
@@ -1659,6 +1662,15 @@
<ref name="unsignedInt"/>
</attribute>
</define>
+ <define name="detect_zeroes">
+ <attribute name='detect_zeroes'>
+ <choice>
+ <value>off</value>
+ <value>on</value>
+ <value>unmap</value>
+ </choice>
+ </attribute>
+ </define>
<define name="controller">
<element name="controller">
<attribute name="index">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3b15cb46d9ec..9137f8368012 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -792,6 +792,12 @@ VIR_ENUM_IMPL(virDomainDiskDiscard, VIR_DOMAIN_DISK_DISCARD_LAST,
"unmap",
"ignore")
+VIR_ENUM_IMPL(virDomainDiskDetectZeros, VIR_DOMAIN_DISK_DETECT_ZEROES_LAST,
+ "default",
+ "off",
+ "on",
+ "unmap")
+
VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
"none",
"yes",
@@ -6566,6 +6572,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
char *mirrorFormat = NULL;
char *mirrorType = NULL;
char *domain_name = NULL;
+ char *detect_zeroes = NULL;
int expected_secret_usage = -1;
int auth_secret_usage = -1;
int ret = 0;
@@ -6703,6 +6710,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
copy_on_read = virXMLPropString(cur, "copy_on_read");
discard = virXMLPropString(cur, "discard");
driverIOThread = virXMLPropString(cur, "iothread");
+ detect_zeroes = virXMLPropString(cur, "detect_zeroes");
} else if (!def->mirror &&
xmlStrEqual(cur->name, BAD_CAST "mirror") &&
!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
@@ -7305,6 +7313,16 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
}
}
+ if (detect_zeroes) {
+ if ((def->detect_zeroes =
+ virDomainDiskDetectZerosTypeFromString(detect_zeroes)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown disk detect_zeroes mode '%s'"),
+ detect_zeroes);
+ goto error;
+ }
+ }
+
if (driverIOThread) {
if (virStrToLong_uip(driverIOThread, NULL, 10, &def->iothread) < 0 ||
def->iothread == 0) {
@@ -18756,6 +18774,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
const char *copy_on_read = virTristateSwitchTypeToString(def->copy_on_read);
const char *sgio = virDomainDeviceSGIOTypeToString(def->sgio);
const char *discard = virDomainDiskDiscardTypeToString(def->discard);
+ const char *detect_zeroes =
virDomainDiskDetectZerosTypeToString(def->detect_zeroes);
if (!type || !def->src->type) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -18810,7 +18829,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
if (def->src->driverName || def->src->format > 0 || def->cachemode
||
def->error_policy || def->rerror_policy || def->iomode ||
def->ioeventfd || def->event_idx || def->copy_on_read ||
- def->discard || def->iothread) {
+ def->discard || def->iothread || def->detect_zeroes) {
virBufferAddLit(buf, "<driver");
virBufferEscapeString(buf, " name='%s'",
def->src->driverName);
if (def->src->format > 0)
@@ -18834,6 +18853,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " discard='%s'", discard);
if (def->iothread)
virBufferAsprintf(buf, " iothread='%u'",
def->iothread);
+ if (def->detect_zeroes)
+ virBufferAsprintf(buf, " detect_zeroes='%s'",
detect_zeroes);
virBufferAddLit(buf, "/>\n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1de3be33e128..06d05eca8ded 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -653,6 +653,15 @@ typedef enum {
VIR_DOMAIN_DISK_DISCARD_LAST
} virDomainDiskDiscard;
+typedef enum {
+ VIR_DOMAIN_DISK_DETECT_ZEROES_DEFAULT = 0,
+ VIR_DOMAIN_DISK_DETECT_ZEROES_OFF,
+ VIR_DOMAIN_DISK_DETECT_ZEROES_ON,
+ VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP,
+
+ VIR_DOMAIN_DISK_DETECT_ZEROES_LAST
+} virDomainDiskDetectZeros;
+
typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
struct _virDomainBlockIoTuneInfo {
unsigned long long total_bytes_sec;
@@ -731,6 +740,7 @@ struct _virDomainDiskDef {
int sgio; /* enum virDomainDeviceSGIO */
int discard; /* enum virDomainDiskDiscard */
unsigned int iothread; /* unused = 0, > 0 specific thread # */
+ int detect_zeroes; /* enum virDomainDiskDetectZeros */
char *domain_name; /* backend domain name */
};
@@ -2986,6 +2996,7 @@ VIR_ENUM_DECL(virDomainDiskIo)
VIR_ENUM_DECL(virDomainDeviceSGIO)
VIR_ENUM_DECL(virDomainDiskTray)
VIR_ENUM_DECL(virDomainDiskDiscard)
+VIR_ENUM_DECL(virDomainDiskDetectZeros)
VIR_ENUM_DECL(virDomainDiskMirrorState)
VIR_ENUM_DECL(virDomainController)
VIR_ENUM_DECL(virDomainControllerModelPCI)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4b4061219881..6f75a8681bec 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -262,6 +262,8 @@ virDomainDiskDefForeachPath;
virDomainDiskDefFree;
virDomainDiskDefNew;
virDomainDiskDefSourceParse;
+virDomainDiskDetectZerosTypeFromString;
+virDomainDiskDetectZerosTypeToString;
virDomainDiskDeviceTypeToString;
virDomainDiskDiscardTypeToString;
virDomainDiskErrorPolicyTypeFromString;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.xml
b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.xml
new file mode 100644
index 000000000000..8953f50f3f92
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.xml
@@ -0,0 +1,45 @@
+<domain type='qemu'>
+ <name>test</name>
+ <uuid>92d7a226-cfae-425b-a6d3-00bbf9ec5c9e</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-0.13'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='hd'/>
+ <bootmenu enable='yes'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' discard='unmap'
detect_zeroes='unmap'/>
+ <source file='/var/lib/libvirt/images/f14.img'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x04' function='0x0'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver discard='ignore' detect_zeroes='off'/>
+ <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-detect-zeroes.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-detect-zeroes.xml
new file mode 120000
index 000000000000..afa3199d4a7e
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-detect-zeroes.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index ef6e35a9cdc0..e62233369e41 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -544,6 +544,7 @@ mymain(void)
DO_TEST("disk-source-pool-mode");
DO_TEST("disk-drive-discard");
+ DO_TEST("disk-drive-detect-zeroes");
DO_TEST("virtio-rng-random");
DO_TEST("virtio-rng-egd");
--
2.7.1