qemu: Support discard for disk

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 commit is contained in:
Osier Yang 2013-05-14 20:44:54 +08:00
parent f60bd7c7a7
commit a7c4202cdd
12 changed files with 112 additions and 0 deletions

View File

@ -1702,6 +1702,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>

View File

@ -1311,6 +1311,9 @@
<optional>
<ref name="copy_on_read"/>
</optional>
<optional>
<ref name="discard"/>
</optional>
<empty/>
</element>
</define>
@ -1406,6 +1409,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">

View File

@ -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");
}

View File

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

View File

@ -142,6 +142,7 @@ virDomainDiskDefFree;
virDomainDiskDefGenSecurityLabelDef;
virDomainDiskDefGetSecurityLabelDef;
virDomainDiskDeviceTypeToString;
virDomainDiskDiscardTypeToString;
virDomainDiskErrorPolicyTypeFromString;
virDomainDiskErrorPolicyTypeToString;
virDomainDiskFindByBusAndDst;

View File

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

View File

@ -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 */
};

View File

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

View File

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

View File

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

View File

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

View File

@ -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");