提交 a7c4202c 编写于 作者: O Osier Yang

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.
上级 f60bd7c7
...@@ -1702,6 +1702,14 @@ ...@@ -1702,6 +1702,14 @@
network. By default copy-on-read is off. network. By default copy-on-read is off.
<span class='since'>Since 0.9.10 (QEMU and KVM only)</span> <span class='since'>Since 0.9.10 (QEMU and KVM only)</span>
</li> </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> </ul>
</dd> </dd>
<dt><code>boot</code></dt> <dt><code>boot</code></dt>
......
...@@ -1311,6 +1311,9 @@ ...@@ -1311,6 +1311,9 @@
<optional> <optional>
<ref name="copy_on_read"/> <ref name="copy_on_read"/>
</optional> </optional>
<optional>
<ref name="discard"/>
</optional>
<empty/> <empty/>
</element> </element>
</define> </define>
...@@ -1406,6 +1409,14 @@ ...@@ -1406,6 +1409,14 @@
<value>off</value> <value>off</value>
</choice> </choice>
</attribute> </attribute>
</define>
<define name="discard">
<attribute name='discard'>
<choice>
<value>on</value>
<value>off</value>
</choice>
</attribute>
</define> </define>
<define name="controller"> <define name="controller">
<element name="controller"> <element name="controller">
......
...@@ -743,6 +743,10 @@ VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST, ...@@ -743,6 +743,10 @@ VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST,
VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST, VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST,
"passthrough") "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_WRITE_FLAGS VIR_DOMAIN_XML_SECURE
#define VIR_DOMAIN_XML_READ_FLAGS VIR_DOMAIN_XML_INACTIVE #define VIR_DOMAIN_XML_READ_FLAGS VIR_DOMAIN_XML_INACTIVE
...@@ -4534,6 +4538,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -4534,6 +4538,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
char *wwn = NULL; char *wwn = NULL;
char *vendor = NULL; char *vendor = NULL;
char *product = NULL; char *product = NULL;
char *discard = NULL;
int expected_secret_usage = -1; int expected_secret_usage = -1;
int auth_secret_usage = -1; int auth_secret_usage = -1;
...@@ -4761,6 +4766,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -4761,6 +4766,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
ioeventfd = virXMLPropString(cur, "ioeventfd"); ioeventfd = virXMLPropString(cur, "ioeventfd");
event_idx = virXMLPropString(cur, "event_idx"); event_idx = virXMLPropString(cur, "event_idx");
copy_on_read = virXMLPropString(cur, "copy_on_read"); copy_on_read = virXMLPropString(cur, "copy_on_read");
discard = virXMLPropString(cur, "discard");
} else if (!mirror && xmlStrEqual(cur->name, BAD_CAST "mirror") && } else if (!mirror && xmlStrEqual(cur->name, BAD_CAST "mirror") &&
!(flags & VIR_DOMAIN_XML_INACTIVE)) { !(flags & VIR_DOMAIN_XML_INACTIVE)) {
char *ready; char *ready;
...@@ -5207,6 +5213,14 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -5207,6 +5213,14 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
def->copy_on_read = cor; 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 (devaddr) {
if (virDomainParseLegacyDeviceAddress(devaddr, if (virDomainParseLegacyDeviceAddress(devaddr,
&def->info.addr.pci) < 0) { &def->info.addr.pci) < 0) {
...@@ -5326,6 +5340,7 @@ cleanup: ...@@ -5326,6 +5340,7 @@ cleanup:
VIR_FREE(ioeventfd); VIR_FREE(ioeventfd);
VIR_FREE(event_idx); VIR_FREE(event_idx);
VIR_FREE(copy_on_read); VIR_FREE(copy_on_read);
VIR_FREE(discard);
VIR_FREE(devaddr); VIR_FREE(devaddr);
VIR_FREE(serial); VIR_FREE(serial);
virStorageEncryptionFree(encryption); virStorageEncryptionFree(encryption);
...@@ -13658,6 +13673,7 @@ virDomainDiskDefFormat(virBufferPtr buf, ...@@ -13658,6 +13673,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx); const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx);
const char *copy_on_read = virDomainVirtioEventIdxTypeToString(def->copy_on_read); const char *copy_on_read = virDomainVirtioEventIdxTypeToString(def->copy_on_read);
const char *sgio = virDomainDiskSGIOTypeToString(def->sgio); const char *sgio = virDomainDiskSGIOTypeToString(def->sgio);
const char *discard = virDomainDiskDiscardTypeToString(def->discard);
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
...@@ -13734,6 +13750,8 @@ virDomainDiskDefFormat(virBufferPtr buf, ...@@ -13734,6 +13750,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " event_idx='%s'", event_idx); virBufferAsprintf(buf, " event_idx='%s'", event_idx);
if (def->copy_on_read) if (def->copy_on_read)
virBufferAsprintf(buf, " copy_on_read='%s'", copy_on_read); virBufferAsprintf(buf, " copy_on_read='%s'", copy_on_read);
if (def->discard)
virBufferAsprintf(buf, " discard='%s'", discard);
virBufferAddLit(buf, "/>\n"); virBufferAddLit(buf, "/>\n");
} }
......
...@@ -625,6 +625,14 @@ enum virDomainDiskSGIO { ...@@ -625,6 +625,14 @@ enum virDomainDiskSGIO {
VIR_DOMAIN_DISK_SGIO_LAST 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; typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
struct _virDomainBlockIoTuneInfo { struct _virDomainBlockIoTuneInfo {
unsigned long long total_bytes_sec; unsigned long long total_bytes_sec;
...@@ -707,6 +715,7 @@ struct _virDomainDiskDef { ...@@ -707,6 +715,7 @@ struct _virDomainDiskDef {
bool rawio_specified; bool rawio_specified;
int rawio; /* no = 0, yes = 1 */ int rawio; /* no = 0, yes = 1 */
int sgio; /* enum virDomainDiskSGIO */ int sgio; /* enum virDomainDiskSGIO */
int discard; /* enum virDomainDiskDiscard */
size_t nseclabels; size_t nseclabels;
virSecurityDeviceLabelDefPtr *seclabels; virSecurityDeviceLabelDefPtr *seclabels;
...@@ -2464,6 +2473,7 @@ VIR_ENUM_DECL(virDomainDiskIo) ...@@ -2464,6 +2473,7 @@ VIR_ENUM_DECL(virDomainDiskIo)
VIR_ENUM_DECL(virDomainDiskSecretType) VIR_ENUM_DECL(virDomainDiskSecretType)
VIR_ENUM_DECL(virDomainDiskSGIO) VIR_ENUM_DECL(virDomainDiskSGIO)
VIR_ENUM_DECL(virDomainDiskTray) VIR_ENUM_DECL(virDomainDiskTray)
VIR_ENUM_DECL(virDomainDiskDiscard)
VIR_ENUM_DECL(virDomainIoEventFd) VIR_ENUM_DECL(virDomainIoEventFd)
VIR_ENUM_DECL(virDomainVirtioEventIdx) VIR_ENUM_DECL(virDomainVirtioEventIdx)
VIR_ENUM_DECL(virDomainDiskCopyOnRead) VIR_ENUM_DECL(virDomainDiskCopyOnRead)
......
...@@ -142,6 +142,7 @@ virDomainDiskDefFree; ...@@ -142,6 +142,7 @@ virDomainDiskDefFree;
virDomainDiskDefGenSecurityLabelDef; virDomainDiskDefGenSecurityLabelDef;
virDomainDiskDefGetSecurityLabelDef; virDomainDiskDefGetSecurityLabelDef;
virDomainDiskDeviceTypeToString; virDomainDiskDeviceTypeToString;
virDomainDiskDiscardTypeToString;
virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeFromString;
virDomainDiskErrorPolicyTypeToString; virDomainDiskErrorPolicyTypeToString;
virDomainDiskFindByBusAndDst; virDomainDiskFindByBusAndDst;
......
...@@ -229,6 +229,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, ...@@ -229,6 +229,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"scsi-generic.bootindex", /* 145 */ "scsi-generic.bootindex", /* 145 */
"mem-merge", "mem-merge",
"vnc-websocket", "vnc-websocket",
"drive-discard",
); );
struct _virQEMUCaps { struct _virQEMUCaps {
...@@ -2244,6 +2245,7 @@ struct virQEMUCapsCommandLineProps { ...@@ -2244,6 +2245,7 @@ struct virQEMUCapsCommandLineProps {
static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = {
{ "machine", "mem-merge", QEMU_CAPS_MEM_MERGE }, { "machine", "mem-merge", QEMU_CAPS_MEM_MERGE },
{ "drive", "discard", QEMU_CAPS_DRIVE_DISCARD },
}; };
static int static int
......
...@@ -186,6 +186,7 @@ enum virQEMUCapsFlags { ...@@ -186,6 +186,7 @@ enum virQEMUCapsFlags {
QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX = 145, /* -device scsi-generic.bootindex */ QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX = 145, /* -device scsi-generic.bootindex */
QEMU_CAPS_MEM_MERGE = 146, /* -machine mem-merge */ QEMU_CAPS_MEM_MERGE = 146, /* -machine mem-merge */
QEMU_CAPS_VNC_WEBSOCKET = 147, /* -vnc x:y,websocket */ 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 */ QEMU_CAPS_LAST, /* this must always be the last item */
}; };
......
...@@ -3274,6 +3274,17 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -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)) { if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
const char *wpolicy = NULL, *rpolicy = NULL; const char *wpolicy = NULL, *rpolicy = NULL;
......
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
<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>
...@@ -585,6 +585,9 @@ mymain(void) ...@@ -585,6 +585,9 @@ mymain(void)
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_COPY_ON_READ, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_COPY_ON_READ,
QEMU_CAPS_VIRTIO_TX_ALG, QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_TX_ALG, QEMU_CAPS_DEVICE,
QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SG_IO); 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", DO_TEST("disk-snapshot",
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT); QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("event_idx", DO_TEST("event_idx",
......
...@@ -261,6 +261,8 @@ mymain(void) ...@@ -261,6 +261,8 @@ mymain(void)
DO_TEST("disk-scsi-disk-vpd"); DO_TEST("disk-scsi-disk-vpd");
DO_TEST("disk-source-pool"); DO_TEST("disk-source-pool");
DO_TEST("disk-drive-discard");
DO_TEST("virtio-rng-random"); DO_TEST("virtio-rng-random");
DO_TEST("virtio-rng-egd"); DO_TEST("virtio-rng-egd");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册