diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b118b49d1af595973fedfe5e3f1764f2d38c7237..e4f9a92cf6e5bb8346d6091ff379a955741a0d71 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1702,6 +1702,14 @@ network. By default copy-on-read is off. Since 0.9.10 (QEMU and KVM only) +
  • + The optional discard 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). + Since 1.0.6 (QEMU and KVM only) +
  • boot
    diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 414fd727dbe6a7d0638072e3a15c6d725b67d3b6..361794e9b1dea856b8e6b1678ccaebb9a3c0e3e1 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1311,6 +1311,9 @@ + + + @@ -1406,6 +1409,14 @@ off + + + + + on + off + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 91f3b3168f487dd4ee7566f205338a86e1aee54d..472b4b406eb0af7907b507e15e8908a3594c16fd 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); @@ -13658,6 +13673,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]; @@ -13734,6 +13750,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 8d4b8683932d07a3126126829f6f05856ad5b0f0..c176a4cd3acf5decc0ade54ecb2df0d7f1ed1d2a 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; @@ -2464,6 +2473,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 cdd0b41baaaf86c0f88690647f3584411f63e1a8..cc734da21e1b9f74dc60c0fecb678bd573fb13a3 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 49cb7a664562fa9c39b1503f1704df5431c3812d..488cbfe94e6cd05253de3c80c8be6ae9d90d4327 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -229,6 +229,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "scsi-generic.bootindex", /* 145 */ "mem-merge", "vnc-websocket", + "drive-discard", ); struct _virQEMUCaps { @@ -2244,6 +2245,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 609f3f939035399407af002a0be03d6699e537b5..173ca777c0cfe09384b45e36051325bfcd8a4762 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -186,6 +186,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX = 145, /* -device scsi-generic.bootindex */ QEMU_CAPS_MEM_MERGE = 146, /* -machine mem-merge */ QEMU_CAPS_VNC_WEBSOCKET = 147, /* -vnc x:y,websocket */ + QEMU_CAPS_DRIVE_DISCARD = 148, /* -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 58eab54a28d1be7cdcc962f762d82a02af2c7a37..5b95c07fa54859e25f00abedd34b8330a77026ad 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3274,6 +3274,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 0000000000000000000000000000000000000000..02e2ddb15159777b5fdb4b5e494cf45461fffd2e --- /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 0000000000000000000000000000000000000000..a6a8135a67043e6ea3fee98f2173cf6436f21dbc --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-discard.xml @@ -0,0 +1,37 @@ + + test + 92d7a226-cfae-425b-a6d3-00bbf9ec5c9e + 1048576 + 1048576 + 1 + + hvm + + + + + + destroy + restart + restart + + /usr/bin/qemu + + + + +
    + + + + + + +
    + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index d0b49b0fe4672c53bfd6241e52303e339ade8b91..ac31d2a9807641ccfccfda31b7a9a9047fb3b7a6 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -585,6 +585,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 92b7383fbeb5cce9c1d2d7a0807766ced5e80e9f..148a05aab0e73bbe941640abd17e75102ef7019c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -261,6 +261,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");