[libvirt] [PATCH] Add unsafe cache mode support for disk driver

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. --- 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 | 3 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 15 ++++++++- 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, 80 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 7476447..21f4c6b 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 36f47a9..13f1aea 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "pci-ohci", "usb-redir", "usb-hub", + "cache-unsafe", ); struct qemu_feature_flags { @@ -918,6 +919,8 @@ qemuCapsComputeCmdFlags(const char *help, 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); if (strstr(help, "readonly=")) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 96b7a3b..97fda0c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -110,6 +110,7 @@ enum qemuCapsFlags { QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */ QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */ QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */ + QEMU_CAPS_DRIVE_CACHE_UNSAFE = 74, /* 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 e8b1157..372f9fb 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) @@ -1623,6 +1625,13 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, "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 +5545,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 ffd30e2..4d757e5 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; } @@ -164,6 +164,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, @@ -399,6 +400,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, @@ -450,6 +452,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 fcb20bb..97b61d1 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 02726f3..73ed045 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1173,8 +1173,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

于 2011年09月20日 04:47, Oskari Saarenmaa 写道:
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. --- 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 | 3 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 15 ++++++++- 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, 80 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 7476447..21f4c6b 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 36f47a9..13f1aea 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "pci-ohci", "usb-redir", "usb-hub", + "cache-unsafe", );
struct qemu_feature_flags { @@ -918,6 +919,8 @@ qemuCapsComputeCmdFlags(const char *help, if (strstr(help, "directsync")) qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC); } + if (strstr(help, "|unsafe")) + qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_UNSAFE);
IMHO this is unsafe indeed, :-) If there is a "|unsafe" not for "cache=", things are different, though there is no another "|unsafe" currently.
if (strstr(help, "format=")) qemuCapsSet(flags, QEMU_CAPS_DRIVE_FORMAT); if (strstr(help, "readonly=")) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 96b7a3b..97fda0c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -110,6 +110,7 @@ enum qemuCapsFlags { QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */ QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */ QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */ + QEMU_CAPS_DRIVE_CACHE_UNSAFE = 74, /* 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 e8b1157..372f9fb 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)
@@ -1623,6 +1625,13 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, "supported by this QEMU")); goto error; } + else if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_UNSAFE&&
Code style, libvirt prefers: if { foo(); } else if { bar(); }
+ !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 +5545,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 ffd30e2..4d757e5 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; }
@@ -164,6 +164,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, @@ -399,6 +400,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, @@ -450,6 +452,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 fcb20bb..97b61d1 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 02726f3..73ed045 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1173,8 +1173,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,
Others looks file, ACK. Osier

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

On 09/21/2011 10:29 AM, Oskari Saarenmaa wrote:
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
I'm thinking that this is enough of a feature to delay until after we decide whether to do a rapid-turnaround 0.9.6 for the qemu workaround.
+++ 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>
Tweak the since wording: <span class="since">Since 0.6.0, "unsafe" since 0.9.x</span> (where x is 6 or 7, depending on delay)
+++ 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);
I'd feel a bit better if we did strstr(help, "cache="), then strchr(str, '\n'), then validated that strstr(str, "|unsafe") falls before the strchr result, since "unsafe" is a string likely to appear elsewhere in future -help output.
+++ 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);
This addition of info->name throughout failed tests output is useful as an independent patch, that we could push even now. Overall, looking pretty good. Hopefully we'll settle out the 0.9.6 decision soon, at which point a v3 of this patch should be worth including. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 09/21/2011 03:14 PM, Eric Blake wrote:
+++ 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);
This addition of info->name throughout failed tests output is useful as an independent patch, that we could push even now.
In fact, I did that split for you and pushed this: From 42b23434b05f8e230e9a7354e773f32ba88687c7 Mon Sep 17 00:00:00 2001 From: Oskari Saarenmaa <os@ohmu.fi> Date: Wed, 21 Sep 2011 19:29:31 +0300 Subject: [PATCH] tests: improve test failure diagnosis * qemuhelptest prints test case name on failure. --- tests/qemuhelptest.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 4a4070a..933d556 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; } -- 1.7.4.4 -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

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. * Improved the reliability of qemu cache type detection. --- Updated patch based on Eric Blake's comments and rebased it to c4111bd0 docs/formatdomain.html.in | 13 +++++-- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 3 +- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 14 ++++++-- src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 14 +++++++- tests/qemuargv2xmltest.c | 1 + tests/qemuhelptest.c | 3 ++ .../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, 84 insertions(+), 13 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..0628d1c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -996,10 +996,15 @@ <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. - <span class="since">Since 0.6.0</span> + "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, + "directsync" since 0.9.5, + "unsafe" since 0.9.7 + </span> </li> <li> The optional <code>error_policy</code> attribute controls 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 7463d7c..a918679 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..8e20e3f 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 { @@ -912,12 +914,16 @@ qemuCapsComputeCmdFlags(const char *help, else if (strstr(help, "-domid")) qemuCapsSet(flags, QEMU_CAPS_DOMID); if (strstr(help, "-drive")) { + const char *cache = strstr(help, "cache="); + qemuCapsSet(flags, QEMU_CAPS_DRIVE); - if (strstr(help, "cache=") && - !strstr(help, "cache=on|off")) { - qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_V2); - if (strstr(help, "directsync")) + if (cache && (p = strchr(cache, ']'))) { + if (memmem(cache, p - cache, "on|off", sizeof("on|off") - 1) == NULL) + qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_V2); + if (memmem(cache, p - cache, "directsync", sizeof("directsync") - 1)) qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC); + if (memmem(cache, p - cache, "unsafe", sizeof("unsafe") - 1)) + 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 933d556..0ff8236 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -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 086fe93..43ed1ea 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1195,8 +1195,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

On 09/22/2011 01:33 PM, Oskari Saarenmaa wrote:
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
s/known/know/
is supported.
* Improved the reliability of qemu cache type detection. --- Updated patch based on Eric Blake's comments and rebased it to c4111bd0
+++ b/docs/formatdomain.html.in @@ -996,10 +996,15 @@ <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. -<span class="since">Since 0.6.0</span> + "writethrough", "writeback", "directsync" (like + "writethrough", but it bypasses the host page cache) and + "unsafe" (host may cache all disk io and sync requests from
s/io and/io, and/
@@ -912,12 +914,16 @@ qemuCapsComputeCmdFlags(const char *help, else if (strstr(help, "-domid")) qemuCapsSet(flags, QEMU_CAPS_DOMID); if (strstr(help, "-drive")) { + const char *cache = strstr(help, "cache="); + qemuCapsSet(flags, QEMU_CAPS_DRIVE); - if (strstr(help, "cache=")&& - !strstr(help, "cache=on|off")) { - qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_V2); - if (strstr(help, "directsync")) + if (cache&& (p = strchr(cache, ']'))) { + if (memmem(cache, p - cache, "on|off", sizeof("on|off") - 1) == NULL) + qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_V2); + if (memmem(cache, p - cache, "directsync", sizeof("directsync") - 1)) qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC); + if (memmem(cache, p - cache, "unsafe", sizeof("unsafe") - 1)) + qemuCapsSet(flags, QEMU_CAPS_DRIVE_CACHE_UNSAFE);
Nice! And indeed, unsafe but not directsync is present in qemu 0.14.0, so this does need another capability bit. ACK and pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
participants (3)
-
Eric Blake
-
Osier Yang
-
Oskari Saarenmaa