QEMU 0.13 introduced cache=unsafe for -drive, this patch exposes
it in the libvirt layer.
* Introduced a new QEMU capability flag ($prefix_CACHE_UNSAFE),
as even if $prefix_CACHE_V2 is set, we can't known if unsafe
is supported.
* qemuhelptest prints test case name on failure.
---
Updated patch based on Osier Yang's comments and rebased it to 3abadf82
docs/formatdomain.html.in | 7 ++--
docs/schemas/domaincommon.rng | 1 +
src/conf/domain_conf.c | 3 +-
src/conf/domain_conf.h | 1 +
src/qemu/qemu_capabilities.c | 4 ++
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 14 +++++++-
tests/qemuargv2xmltest.c | 1 +
tests/qemuhelptest.c | 19 ++++++-----
.../qemuxml2argv-disk-drive-cache-unsafe.args | 5 +++
.../qemuxml2argv-disk-drive-cache-unsafe.xml | 33 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 3 ++
tools/virsh.pod | 4 +-
13 files changed, 81 insertions(+), 16 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0a7abaf..8087327 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -996,9 +996,10 @@
<li>
The optional <code>cache</code> attribute controls the
cache mechanism, possible values are "default", "none",
- "writethrough", "writeback", and "directsync".
"directsync"
- is like "writethrough", but it bypasses the host page
- cache.
+ "writethrough", "writeback", "directsync"
(like
+ "writethrough", but it bypasses the host page cache) and
+ "unsafe" (host may cache all disk io and sync requests from
+ guest are ignored).
<span class="since">Since 0.6.0</span>
</li>
<li>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d0da41c..be98be0 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -848,6 +848,7 @@
<value>writeback</value>
<value>writethrough</value>
<value>directsync</value>
+ <value>unsafe</value>
</choice>
</attribute>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index eebcba0..f38c1d8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -164,7 +164,8 @@ VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
"none",
"writethrough",
"writeback",
- "directsync")
+ "directsync",
+ "unsafe")
VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
"default",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 371f270..86b4c79 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -192,6 +192,7 @@ enum virDomainDiskCache {
VIR_DOMAIN_DISK_CACHE_WRITETHRU,
VIR_DOMAIN_DISK_CACHE_WRITEBACK,
VIR_DOMAIN_DISK_CACHE_DIRECTSYNC,
+ VIR_DOMAIN_DISK_CACHE_UNSAFE,
VIR_DOMAIN_DISK_CACHE_LAST
};
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 850d46e..fcb9c8b 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -137,6 +137,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"usb-redir",
"usb-hub",
"no-shutdown",
+
+ "cache-unsafe", /* 75 */
);
struct qemu_feature_flags {
@@ -918,6 +920,8 @@ qemuCapsComputeCmdFlags(const char *help,
qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_V2);
if (strstr(help, "directsync"))
qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC);
+ if (strstr(help, "|unsafe"))
+ qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_UNSAFE);
}
if (strstr(help, "format="))
qemuCapsSet(flags, QEMU_CAPS_DRIVE_FORMAT);
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 74d3ab2..ae3de90 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -112,6 +112,8 @@ enum qemuCapsFlags {
QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */
QEMU_CAPS_NO_SHUTDOWN = 74, /* usable -no-shutdown */
+ QEMU_CAPS_DRIVE_CACHE_UNSAFE = 75, /* Is cache=unsafe supported? */
+
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 0adc56a..9174a5f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -66,14 +66,16 @@ VIR_ENUM_IMPL(qemuDiskCacheV1, VIR_DOMAIN_DISK_CACHE_LAST,
"off",
"off", /* writethrough not supported, so for safety, disable */
"on", /* Old 'on' was equivalent to 'writeback'
*/
- "off"); /* directsync not supported, for safety, disable */
+ "off", /* directsync not supported, for safety, disable */
+ "off"); /* unsafe not supported, for safety, disable */
VIR_ENUM_IMPL(qemuDiskCacheV2, VIR_DOMAIN_DISK_CACHE_LAST,
"default",
"none",
"writethrough",
"writeback",
- "directsync");
+ "directsync",
+ "unsafe");
VIR_ENUM_DECL(qemuVideo)
@@ -1622,6 +1624,12 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
_("disk cache mode 'directsync' is not
"
"supported by this QEMU"));
goto error;
+ } else if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_UNSAFE &&
+ !qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_CACHE_UNSAFE)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("disk cache mode 'unsafe' is not "
+ "supported by this QEMU"));
+ goto error;
}
} else {
mode = qemuDiskCacheV1TypeToString(disk->cachemode);
@@ -5536,6 +5544,8 @@ qemuParseCommandLineDisk(virCapsPtr caps,
def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITETHRU;
else if (STREQ(values[i], "directsync"))
def->cachemode = VIR_DOMAIN_DISK_CACHE_DIRECTSYNC;
+ else if (STREQ(values[i], "unsafe"))
+ def->cachemode = VIR_DOMAIN_DISK_CACHE_UNSAFE;
} else if (STREQ(keywords[i], "werror") ||
STREQ(keywords[i], "rerror")) {
if (STREQ(values[i], "stop"))
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 91f15af..6a79630 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -169,6 +169,7 @@ mymain(void)
DO_TEST("disk-drive-cache-v2-wb");
DO_TEST("disk-drive-cache-v2-none");
DO_TEST("disk-drive-cache-directsync");
+ DO_TEST("disk-drive-cache-unsafe");
DO_TEST("disk-drive-network-nbd");
DO_TEST("disk-drive-network-rbd");
DO_TEST("disk-drive-network-sheepdog");
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index 4a4070a..0ff8236 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -77,8 +77,8 @@ static int testHelpStrParsing(const void *data)
if (STRNEQ(got, expected)) {
fprintf(stderr,
- "Computed flags do not match: got %s, expected %s\n",
- got, expected);
+ "%s: computed flags do not match: got %s, expected %s\n",
+ info->name, got, expected);
if (getenv("VIR_TEST_DEBUG"))
printMismatchedFlags(flags, info->flags);
@@ -87,22 +87,22 @@ static int testHelpStrParsing(const void *data)
}
if (version != info->version) {
- fprintf(stderr, "Parsed versions do not match: got %u, expected %u\n",
- version, info->version);
+ fprintf(stderr, "%s: parsed versions do not match: got %u, expected
%u\n",
+ info->name, version, info->version);
goto cleanup;
}
if (is_kvm != info->is_kvm) {
fprintf(stderr,
- "Parsed is_kvm flag does not match: got %u, expected %u\n",
- is_kvm, info->is_kvm);
+ "%s: parsed is_kvm flag does not match: got %u, expected
%u\n",
+ info->name, is_kvm, info->is_kvm);
goto cleanup;
}
if (kvm_version != info->kvm_version) {
fprintf(stderr,
- "Parsed KVM versions do not match: got %u, expected %u\n",
- kvm_version, info->kvm_version);
+ "%s: parsed KVM versions do not match: got %u, expected %u\n",
+ info->name, kvm_version, info->kvm_version);
goto cleanup;
}
@@ -165,6 +165,7 @@ mymain(void)
QEMU_CAPS_MIGRATE_QEMU_TCP,
QEMU_CAPS_MIGRATE_QEMU_EXEC,
QEMU_CAPS_DRIVE_CACHE_V2,
+ QEMU_CAPS_DRIVE_CACHE_UNSAFE,
QEMU_CAPS_KVM,
QEMU_CAPS_DRIVE_FORMAT,
QEMU_CAPS_DRIVE_SERIAL,
@@ -408,6 +409,7 @@ mymain(void)
QEMU_CAPS_MIGRATE_QEMU_TCP,
QEMU_CAPS_MIGRATE_QEMU_EXEC,
QEMU_CAPS_DRIVE_CACHE_V2,
+ QEMU_CAPS_DRIVE_CACHE_UNSAFE,
QEMU_CAPS_KVM,
QEMU_CAPS_DRIVE_FORMAT,
QEMU_CAPS_DRIVE_SERIAL,
@@ -460,6 +462,7 @@ mymain(void)
QEMU_CAPS_MIGRATE_QEMU_TCP,
QEMU_CAPS_MIGRATE_QEMU_EXEC,
QEMU_CAPS_DRIVE_CACHE_V2,
+ QEMU_CAPS_DRIVE_CACHE_UNSAFE,
QEMU_CAPS_KVM,
QEMU_CAPS_DRIVE_FORMAT,
QEMU_CAPS_DRIVE_SERIAL,
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.args
b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.args
new file mode 100644
index 0000000..f8ddcd8
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.args
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi -boot c -drive file=/dev/HostVG/QEMUGuest1,if=ide,bus=0,unit=0,\
+format=qcow2,cache=unsafe -drive file=/dev/HostVG/QEMUGuest2,if=ide,\
+media=cdrom,bus=1,unit=0,format=raw -net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.xml
b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.xml
new file mode 100644
index 0000000..37185f6
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-unsafe.xml
@@ -0,0 +1,33 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219136</memory>
+ <currentMemory>219136</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='qcow2' cache='unsafe'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
unit='0'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1'
unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 1dc6a01..9e174b3 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -341,6 +341,9 @@ mymain(void)
DO_TEST("disk-drive-cache-directsync", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2,
QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC, QEMU_CAPS_DRIVE_FORMAT);
+ DO_TEST("disk-drive-cache-unsafe", false,
+ QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2,
+ QEMU_CAPS_DRIVE_CACHE_UNSAFE, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-network-nbd", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-network-rbd", false,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 88dee26..463bee7 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1192,8 +1192,8 @@ floppy device; consider using B<update-device> for this usage
instead.
I<mode> can specify the two specific mode I<readonly> or I<shareable>.
I<persistent> indicates the changes will affect the next boot of the domain.
I<sourcetype> can indicate the type of source (block|file)
-I<cache> can be one of "default", "none",
"writethrough", "writeback", or
-"directsync".
+I<cache> can be one of "default", "none",
"writethrough", "writeback",
+"directsync" or "unsafe".
I<serial> is the serial of disk device. I<shareable> indicates the disk
device
is shareable between domains.
I<address> is the address of disk device in the form of
pci:domain.bus.slot.function,
--
1.7.6.2