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 +++++++
.../qemuxml2argv-disk-drive-detect-zeros.xml | 37 ++++++++++++++++++++++
tests/qemuxml2xmltest.c | 1 +
6 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeros.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a8bd48e97129..bc925ea330c7 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2498,6 +2498,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_zeros</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 4804c692e210..de8d3614d24f 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1576,6 +1576,9 @@
<optional>
<ref name="driverIOThread"/>
</optional>
+ <optional>
+ <ref name="detect_zeros"/>
+ </optional>
<empty/>
</element>
</define>
@@ -1659,6 +1662,15 @@
<ref name="unsignedInt"/>
</attribute>
</define>
+ <define name="detect_zeros">
+ <attribute name='detect_zeros'>
+ <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 5200c278914e..cb83266c92a4 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_ZEROS_LAST,
+ "default",
+ "off",
+ "on",
+ "unmap")
+
VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
"none",
"yes",
@@ -6532,6 +6538,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
char *mirrorFormat = NULL;
char *mirrorType = NULL;
char *domain_name = NULL;
+ char *detect_zeros = NULL;
int expected_secret_usage = -1;
int auth_secret_usage = -1;
int ret = 0;
@@ -6669,6 +6676,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
copy_on_read = virXMLPropString(cur, "copy_on_read");
discard = virXMLPropString(cur, "discard");
driverIOThread = virXMLPropString(cur, "iothread");
+ detect_zeros = virXMLPropString(cur, "detect_zeros");
} else if (!def->mirror &&
xmlStrEqual(cur->name, BAD_CAST "mirror") &&
!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
@@ -7271,6 +7279,16 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
}
}
+ if (detect_zeros) {
+ if ((def->detect_zeros =
+ virDomainDiskDetectZerosTypeFromString(detect_zeros)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown disk detect_zeros mode '%s'"),
+ detect_zeros);
+ goto error;
+ }
+ }
+
if (driverIOThread) {
if (virStrToLong_uip(driverIOThread, NULL, 10, &def->iothread) < 0 ||
def->iothread == 0) {
@@ -18789,6 +18807,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_zeros =
virDomainDiskDetectZerosTypeToString(def->detect_zeros);
if (!type || !def->src->type) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -18843,7 +18862,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_zeros) {
virBufferAddLit(buf, "<driver");
virBufferEscapeString(buf, " name='%s'",
def->src->driverName);
if (def->src->format > 0)
@@ -18867,6 +18886,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " discard='%s'", discard);
if (def->iothread)
virBufferAsprintf(buf, " iothread='%u'",
def->iothread);
+ if (def->detect_zeros)
+ virBufferAsprintf(buf, " detect_zeros='%s'",
detect_zeros);
virBufferAddLit(buf, "/>\n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index cec681a788be..32b74ee60354 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -652,6 +652,15 @@ typedef enum {
VIR_DOMAIN_DISK_DISCARD_LAST
} virDomainDiskDiscard;
+typedef enum {
+ VIR_DOMAIN_DISK_DETECT_ZEROS_DEFAULT = 0,
+ VIR_DOMAIN_DISK_DETECT_ZEROS_OFF,
+ VIR_DOMAIN_DISK_DETECT_ZEROS_ON,
+ VIR_DOMAIN_DISK_DETECT_ZEROS_UNMAP,
+
+ VIR_DOMAIN_DISK_DETECT_ZEROS_LAST
+} virDomainDiskDetectZeros;
+
typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
struct _virDomainBlockIoTuneInfo {
unsigned long long total_bytes_sec;
@@ -730,6 +739,7 @@ struct _virDomainDiskDef {
int sgio; /* enum virDomainDeviceSGIO */
int discard; /* enum virDomainDiskDiscard */
unsigned int iothread; /* unused = 0, > 0 specific thread # */
+ int detect_zeros; /* enum virDomainDiskDetectZeros */
char *domain_name; /* backend domain name */
};
@@ -3000,6 +3010,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/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeros.xml
b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeros.xml
new file mode 100644
index 000000000000..05494264d77a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeros.xml
@@ -0,0 +1,37 @@
+<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_zeros='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_zeros='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'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index f967ceb94d0c..2b3db38b756f 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -529,6 +529,7 @@ mymain(void)
DO_TEST("disk-source-pool-mode");
DO_TEST_DIFFERENT("disk-drive-discard");
+ DO_TEST("disk-drive-detect-zeros");
DO_TEST("virtio-rng-random");
DO_TEST("virtio-rng-egd");
--
2.6.4