[libvirt] [PATCH v2 0/2] Enable detection for zero writes

This is a second version with few things fixed. The main difference is that now this series uses zeroes instead of zeros. The latter was chosen at first just because there were more occurences in our codebase, but the former is used now to minimise the confusion -- mainly when none of the versions were used when interfacing with the user or mgmt app. The naming is kept from the previous version despite the discussion as I believe this is pretty general. Also the default value is not changed to 'off' in order for it to be general enough (some hypervisors might choose a different default in the future). Martin Kletzander (2): conf: Add support of zero-detection for disks qemu: Add support for zero-detection writes 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 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 11 ++++++ tests/qemucapabilitiesdata/caps_2.1.1-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 1 + .../qemuxml2argv-disk-drive-detect-zeroes.args | 27 +++++++++++++ .../qemuxml2argv-disk-drive-detect-zeroes.xml | 45 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 3 ++ .../qemuxml2xmlout-disk-drive-detect-zeroes.xml | 1 + tests/qemuxml2xmltest.c | 1 + 17 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-detect-zeroes.xml -- 2.7.1

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@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

Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 11 +++++++++ tests/qemucapabilitiesdata/caps_2.1.1-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 1 + .../qemuxml2argv-disk-drive-detect-zeroes.args | 27 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 3 +++ 9 files changed, 48 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.args diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 1018d6c3cf3c..400c5ed21174 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -315,6 +315,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "vserport-change-event", /* 210 */ "virtio-balloon-pci.deflate-on-oom", "mptsas1068", + "drive-detect-zeroes", ); @@ -2616,6 +2617,7 @@ static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { { "machine", "mem-merge", QEMU_CAPS_MEM_MERGE }, { "machine", "vmport", QEMU_CAPS_MACHINE_VMPORT_OPT }, { "drive", "discard", QEMU_CAPS_DRIVE_DISCARD }, + { "drive", "detect-zeroes", QEMU_CAPS_DRIVE_DETECT_ZEROES }, { "realtime", "mlock", QEMU_CAPS_MLOCK }, { "boot-opts", "strict", QEMU_CAPS_BOOT_STRICT }, { "boot-opts", "reboot-timeout", QEMU_CAPS_REBOOT_TIMEOUT }, diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index b73c529e768a..5fcabe6d3e83 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -344,6 +344,7 @@ typedef enum { QEMU_CAPS_VIRTIO_BALLOON_AUTODEFLATE, /* virtio-balloon-{device,pci,ccw}. * deflate-on-oom */ QEMU_CAPS_SCSI_MPTSAS1068, /* -device mptsas1068 */ + QEMU_CAPS_DRIVE_DETECT_ZEROES, /* -drive detect_zeroes= */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 78423e7046d9..5b68f0052728 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1280,6 +1280,17 @@ qemuBuildDriveStr(virConnectPtr conn, } } + if (disk->detect_zeroes) { + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DETECT_ZEROES)) { + virBufferAsprintf(&opt, ",detect_zeroes=%s", + virDomainDiskDetectZerosTypeToString(disk->detect_zeroes)); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("detect_zeroes is not supported by this QEMU binary")); + goto error; + } + } + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON)) { const char *wpolicy = NULL, *rpolicy = NULL; diff --git a/tests/qemucapabilitiesdata/caps_2.1.1-1.caps b/tests/qemucapabilitiesdata/caps_2.1.1-1.caps index 332b85abeb2e..76b9ff4f4ed2 100644 --- a/tests/qemucapabilitiesdata/caps_2.1.1-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.1.1-1.caps @@ -160,4 +160,5 @@ <flag name='e1000'/> <flag name='virtio-net'/> <flag name='vserport-change-event'/> + <flag name='drive-detect-zeroes'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_2.4.0-1.caps b/tests/qemucapabilitiesdata/caps_2.4.0-1.caps index e41154276291..617e2c6bcfdd 100644 --- a/tests/qemucapabilitiesdata/caps_2.4.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.4.0-1.caps @@ -171,4 +171,5 @@ <flag name='ich9-disable-s4'/> <flag name='vserport-change-event'/> <flag name='virtio-balloon-pci.deflate-on-oom'/> + <flag name='drive-detect-zeroes'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_2.5.0-1.caps b/tests/qemucapabilitiesdata/caps_2.5.0-1.caps index 931bc4fbcc58..0ba45105a6ac 100644 --- a/tests/qemucapabilitiesdata/caps_2.5.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.5.0-1.caps @@ -172,4 +172,5 @@ <flag name='ich9-disable-s4'/> <flag name='vserport-change-event'/> <flag name='virtio-balloon-pci.deflate-on-oom'/> + <flag name='drive-detect-zeroes'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-1.caps b/tests/qemucapabilitiesdata/caps_2.6.0-1.caps index f32d5aaa4742..0d417c533801 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.6.0-1.caps @@ -174,4 +174,5 @@ <flag name='ich9-disable-s4'/> <flag name='vserport-change-event'/> <flag name='virtio-balloon-pci.deflate-on-oom'/> + <flag name='drive-detect-zeroes'/> </qemuCaps> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.args new file mode 100644 index 000000000000..5aecc4190bb6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-detect-zeroes.args @@ -0,0 +1,27 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu \ +-name test \ +-S \ +-M pc-0.13 \ +-m 1024 \ +-smp 1 \ +-uuid 92d7a226-cfae-425b-a6d3-00bbf9ec5c9e \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi \ +-boot dc \ +-usb \ +-drive file=/var/lib/libvirt/images/f14.img,format=qcow2,if=none,\ +id=drive-virtio-disk0,discard=unmap,detect_zeroes=unmap \ +-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-drive file=/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso,format=raw,if=none,\ +media=cdrom,id=drive-ide0-1-0,discard=ignore,detect_zeroes=off \ +-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 854623dbe249..e8db7eccd2c4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -888,6 +888,9 @@ mymain(void) QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SG_IO); DO_TEST("disk-drive-discard", QEMU_CAPS_DRIVE_DISCARD); + DO_TEST("disk-drive-detect-zeroes", + QEMU_CAPS_DRIVE_DISCARD, + QEMU_CAPS_DRIVE_DETECT_ZEROES); DO_TEST("disk-snapshot", NONE); DO_TEST_FAILURE("disk-same-targets", QEMU_CAPS_SCSI_LSI, -- 2.7.1

On Tue, Feb 23, 2016 at 15:56:23 +0100, Martin Kletzander wrote:
This is a second version with few things fixed. The main difference is that now this series uses zeroes instead of zeros. The latter was chosen at first just because there were more occurences in our codebase, but the former is used now to minimise the confusion -- mainly when none of the versions were used when interfacing with the user or mgmt app.
The naming is kept from the previous version despite the discussion as I believe this is pretty general. Also the default value is not changed to 'off' in order for it to be general enough (some hypervisors might choose a different default in the future).
I'm about to add zero detection while doing block copy so I'll see how that goes with this series and I'll review it once I straighten up design of the feature of mine. Peter
participants (2)
-
Martin Kletzander
-
Peter Krempa