QEMU introduced "discard" option for drive since commit a9384aff53, <...> @var{discard} is one of "ignore" (or "off") or "unmap" (or "on") and controls whether @dfn{discard} (also known as @dfn{trim} or @dfn{unmap}) requests are ignored or passed to the filesystem. Some machine types may not support discard requests. </...> This patch exposes the support in libvirt. QEMU supported "discard" for "-drive" since v1.5.0-rc0: % git tag --contains a9384aff53 contains v1.5.0-rc0 v1.5.0-rc1 So this only detects the capability bit using virQEMUCapsProbeQMPCommandLine. --- This is on top of https://www.redhat.com/archives/libvir-list/2013-May/msg00979.html --- docs/formatdomain.html.in | 8 +++++ docs/schemas/domaincommon.rng | 11 +++++++ src/conf/domain_conf.c | 18 +++++++++++ src/conf/domain_conf.h | 10 ++++++ src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 11 +++++++ .../qemuxml2argv-disk-drive-discard.args | 8 +++++ .../qemuxml2argv-disk-drive-discard.xml | 37 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 3 ++ tests/qemuxml2xmltest.c | 2 ++ 12 files changed, 112 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 9ade507..a73d72e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1681,6 +1681,14 @@ network. By default copy-on-read is off. <span class='since'>Since 0.9.10 (QEMU and KVM only)</span> </li> + <li> + The optional <code>discard</code> attribute controls whether + to discard (also known as "trim" or "unmap") requests are + ignored or passed to the filesystem. The value can be either + "on" (allow the discard request to be passed) or "off" (ingore + the discard request). + <span class='since'>Since 1.0.6 (QEMU and KVM only)</span> + </li> </ul> </dd> <dt><code>boot</code></dt> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8004428..2083e95 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1304,6 +1304,9 @@ <optional> <ref name="copy_on_read"/> </optional> + <optional> + <ref name="discard"/> + </optional> <empty/> </element> </define> @@ -1399,6 +1402,14 @@ <value>off</value> </choice> </attribute> + </define> + <define name="discard"> + <attribute name='discard'> + <choice> + <value>on</value> + <value>off</value> + </choice> + </attribute> </define> <define name="controller"> <element name="controller"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 862b997..f632c02 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -743,6 +743,10 @@ VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST, VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST, "passthrough") +VIR_ENUM_IMPL(virDomainDiskDiscard, VIR_DOMAIN_DISK_DISCARD_LAST, + "default", + "on", + "off") #define VIR_DOMAIN_XML_WRITE_FLAGS VIR_DOMAIN_XML_SECURE #define VIR_DOMAIN_XML_READ_FLAGS VIR_DOMAIN_XML_INACTIVE @@ -4534,6 +4538,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, char *wwn = NULL; char *vendor = NULL; char *product = NULL; + char *discard = NULL; int expected_secret_usage = -1; int auth_secret_usage = -1; @@ -4761,6 +4766,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, ioeventfd = virXMLPropString(cur, "ioeventfd"); event_idx = virXMLPropString(cur, "event_idx"); copy_on_read = virXMLPropString(cur, "copy_on_read"); + discard = virXMLPropString(cur, "discard"); } else if (!mirror && xmlStrEqual(cur->name, BAD_CAST "mirror") && !(flags & VIR_DOMAIN_XML_INACTIVE)) { char *ready; @@ -5207,6 +5213,14 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, def->copy_on_read = cor; } + if (discard) { + if ((def->discard = virDomainDiskDiscardTypeFromString(discard)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk discard mode '%s'"), discard); + goto error; + } + } + if (devaddr) { if (virDomainParseLegacyDeviceAddress(devaddr, &def->info.addr.pci) < 0) { @@ -5326,6 +5340,7 @@ cleanup: VIR_FREE(ioeventfd); VIR_FREE(event_idx); VIR_FREE(copy_on_read); + VIR_FREE(discard); VIR_FREE(devaddr); VIR_FREE(serial); virStorageEncryptionFree(encryption); @@ -13642,6 +13657,7 @@ virDomainDiskDefFormat(virBufferPtr buf, const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx); const char *copy_on_read = virDomainVirtioEventIdxTypeToString(def->copy_on_read); const char *sgio = virDomainDiskSGIOTypeToString(def->sgio); + const char *discard = virDomainDiskDiscardTypeToString(def->discard); char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -13718,6 +13734,8 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " event_idx='%s'", event_idx); if (def->copy_on_read) virBufferAsprintf(buf, " copy_on_read='%s'", copy_on_read); + if (def->discard) + virBufferAsprintf(buf, " discard='%s'", discard); virBufferAddLit(buf, "/>\n"); } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a9d3410..67ea91e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -625,6 +625,14 @@ enum virDomainDiskSGIO { VIR_DOMAIN_DISK_SGIO_LAST }; +enum virDomainDiskDiscard { + VIR_DOMAIN_DISK_DISCARD_DEFAULT = 0, + VIR_DOMAIN_DISK_DISCARD_ON, + VIR_DOMAIN_DISK_DISCARD_OFF, + + VIR_DOMAIN_DISK_DISCARD_LAST +}; + typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo; struct _virDomainBlockIoTuneInfo { unsigned long long total_bytes_sec; @@ -707,6 +715,7 @@ struct _virDomainDiskDef { bool rawio_specified; int rawio; /* no = 0, yes = 1 */ int sgio; /* enum virDomainDiskSGIO */ + int discard; /* enum virDomainDiskDiscard */ size_t nseclabels; virSecurityDeviceLabelDefPtr *seclabels; @@ -2462,6 +2471,7 @@ VIR_ENUM_DECL(virDomainDiskIo) VIR_ENUM_DECL(virDomainDiskSecretType) VIR_ENUM_DECL(virDomainDiskSGIO) VIR_ENUM_DECL(virDomainDiskTray) +VIR_ENUM_DECL(virDomainDiskDiscard) VIR_ENUM_DECL(virDomainIoEventFd) VIR_ENUM_DECL(virDomainVirtioEventIdx) VIR_ENUM_DECL(virDomainDiskCopyOnRead) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cdd0b41..cc734da 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -142,6 +142,7 @@ virDomainDiskDefFree; virDomainDiskDefGenSecurityLabelDef; virDomainDiskDefGetSecurityLabelDef; virDomainDiskDeviceTypeToString; +virDomainDiskDiscardTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; virDomainDiskFindByBusAndDst; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c711e92..e6cb091 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -228,6 +228,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "scsi-generic.bootindex", /* 145 */ "mem-merge", + "drive-discard", ); struct _virQEMUCaps { @@ -2243,6 +2244,7 @@ struct virQEMUCapsCommandLineProps { static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { { "machine", "mem-merge", QEMU_CAPS_MEM_MERGE }, + { "drive", "discard", QEMU_CAPS_DRIVE_DISCARD }, }; static int diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 477e526..e30a550 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -185,6 +185,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_SCSI_GENERIC = 144, /* -device scsi-generic */ QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX = 145, /* -device scsi-generic.bootindex */ QEMU_CAPS_MEM_MERGE = 146, /* -machine mem-merge */ + QEMU_CAPS_DRIVE_DISCARD = 147, /* -drive discard=off(ignore)|on(unmap) */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index eddc263..053f553 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3267,6 +3267,17 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, } } + if (disk->discard) { + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DISCARD)) { + virBufferAsprintf(&opt, ",discard=%s", + virDomainDiskDiscardTypeToString(disk->discard)); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("discard 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/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.args new file mode 100644 index 0000000..02e2ddb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.args @@ -0,0 +1,8 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \ +/usr/bin/qemu -S -M pc-0.13 -m 1024 -smp 1 -nographic -nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot dc -usb \ +-drive file=/var/lib/libvirt/images/f14.img,if=none,id=drive-virtio-disk0,discard=on \ +-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,if=none,media=cdrom,id=drive-ide0-1-0,discard=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/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.xml new file mode 100644 index 0000000..a6a8135 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.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='on'/> + <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 name='qemu' type='raw' discard='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/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 98ceb83..46dd7de 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -579,6 +579,9 @@ mymain(void) QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_COPY_ON_READ, QEMU_CAPS_VIRTIO_TX_ALG, QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SG_IO); + DO_TEST("disk-drive-discard", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_DISCARD, + QEMU_CAPS_DEVICE); DO_TEST("disk-snapshot", QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT); DO_TEST("event_idx", diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 492ac60..ffb0e87 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -259,6 +259,8 @@ mymain(void) DO_TEST("disk-scsi-disk-vpd"); DO_TEST("disk-source-pool"); + DO_TEST("disk-drive-discard"); + DO_TEST("virtio-rng-random"); DO_TEST("virtio-rng-egd"); -- 1.8.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list