On 08/26/14 13:21, Eric Blake wrote:
Upstream qemu 1.4 added some drive-mirror tunables not present
when it was first introduced in 1.3. Management apps may want
to set these in some cases (for example, without tuning
granularity down to sector size, a copy may end up occupying
more bytes than the original because an entire cluster is
copied even when only a sector within the cluster is dirty,
although tuning it down results in more CPU time to do the
copy). I haven't personally needed to use the parameters, but
since they exist, and since the new API supports virTypedParams,
we might as well expose them.
Since the tuning parameters aren't often used, and omitted from
the QMP command when unspecified, I think it is safe to rely on
qemu 1.3 to issue an error about them being unsupported, rather
than trying to create a new capability bit in libvirt.
Meanwhile, all versions of qemu from 1.4 to 2.1 have a bug where
a bad granularity (such as non-power-of-2) gives a poor message:
error: internal error: unable to execute QEMU command 'drive-mirror': Invalid
parameter 'drive-virtio-disk0'
because of abuse of QERR_INVALID_PARAMETER (which is supposed to
name the parameter that was given a bad value, rather than the
value passed to some other parameter). I don't see that a
capability check will help, so we'll just live with it (and I'll
send a patch to get qemu 2.2 to give a nicer message).
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror): Add
parameters.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror): Likewise.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror):
Likewise.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDriveMirror):
Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockCopyCommon): Likewise.
(qemuDomainBlockRebase, qemuDomainBlockCopy): Adjust callers.
* src/qemu/qemu_migration.c (qemuMigrationDriveMirror): Likewise.
* tests/qemumonitorjsontest.c (qemuMonitorJSONDriveMirror): Likewise.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Maybe I need to tweak libvirt's handler to report a nicer message
if qemu reports an invalid parameter, since playing the qemu
message verbatim isn't very informative.
src/qemu/qemu_driver.c | 18 +++++-------------
src/qemu/qemu_migration.c | 2 +-
src/qemu/qemu_monitor.c | 8 +++++---
src/qemu/qemu_monitor.h | 2 ++
src/qemu/qemu_monitor_json.c | 3 +++
src/qemu/qemu_monitor_json.h | 2 ++
tests/qemumonitorjsontest.c | 2 +-
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4876617..d43d257 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15281,6 +15281,8 @@ qemuDomainBlockCopyCommon(virDomainObjPtr *vmptr,
const char *path,
virStorageSourcePtr dest,
unsigned long bandwidth,
+ int granularity,
+ int buf_size,
int ??
unsigned int flags)
{
virDomainObjPtr vm = *vmptr;
@@ -15421,7 +15423,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr *vmptr,
/* Actually start the mirroring */
qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorDriveMirror(priv->mon, device, dest->path, format,
- bandwidth, flags);
+ bandwidth, granularity, buf_size, flags);
virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
qemuDomainObjExitMonitor(driver, vm);
if (ret < 0) {
@@ -15498,7 +15500,7 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const
char *base,
* and VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT map to the same value
* as for block copy. */
ret = qemuDomainBlockCopyCommon(&vm, dom->conn, path, dest,
- bandwidth, flags);
+ bandwidth, 0, 0, flags);
cleanup:
if (vm)
@@ -15561,23 +15563,13 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *disk, const
char *destxml,
buf_size = params[i].value.ui;
}
}
- if (granularity) {
- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
- _("granularity tuning not supported yet"));
- goto cleanup;
- }
- if (buf_size) {
- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
- _("buffer size tuning not supported yet"));
- goto cleanup;
- }
if (!(dest = virDomainDiskDefSourceParse(destxml, vm->def, driver->xmlopt,
VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
ret = qemuDomainBlockCopyCommon(&vm, dom->conn, disk, dest,
- bandwidth, flags);
+ bandwidth, granularity, buf_size, flags);
both granularity and bufsize are unsigned here!
cleanup:
virStorageSourceFree(dest);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 9cfb77e..111f6af 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1279,7 +1279,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
goto error;
mon_ret = qemuMonitorDriveMirror(priv->mon, diskAlias, nbd_dest,
- NULL, speed, mirror_flags);
+ NULL, speed, 0, 0, mirror_flags);
qemuDomainObjExitMonitor(driver, vm);
if (mon_ret < 0)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index d5ba08d..0332091 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3182,14 +3182,16 @@ int
qemuMonitorDriveMirror(qemuMonitorPtr mon,
const char *device, const char *file,
const char *format, unsigned long bandwidth,
+ unsigned int granularity, unsigned int buf_size,
unsigned int flags)
{
int ret = -1;
unsigned long long speed;
VIR_DEBUG("mon=%p, device=%s, file=%s, format=%s, bandwidth=%ld, "
- "flags=%x",
- mon, device, file, NULLSTR(format), bandwidth, flags);
+ "granularity=%#x, buf_size=%#x, flags=%x",
Clever way to check the power-of-2-ness, although bufsize would be beter
off with %u.
+ mon, device, file, NULLSTR(format), bandwidth,
granularity,
+ buf_size, flags);
/* Convert bandwidth MiB to bytes - unfortunately the JSON QMP protocol is
* limited to LLONG_MAX also for unsigned values */
@@ -3204,7 +3206,7 @@ qemuMonitorDriveMirror(qemuMonitorPtr mon,
if (mon->json)
ret = qemuMonitorJSONDriveMirror(mon, device, file, format, speed,
- flags);
+ granularity, buf_size, flags);
else
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("drive-mirror requires JSON monitor"));
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 4fd6f01..9da7ee4 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -650,6 +650,8 @@ int qemuMonitorDriveMirror(qemuMonitorPtr mon,
const char *file,
const char *format,
unsigned long bandwidth,
+ unsigned int granularity,
+ unsigned int buf_size,
unsigned int flags)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorDrivePivot(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 62e7d5d..dcbb693 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3397,6 +3397,7 @@ int
qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
const char *device, const char *file,
const char *format, unsigned long long speed,
+ unsigned int granularity, unsigned int buf_size,
unsigned int flags)
{
int ret = -1;
@@ -3409,6 +3410,8 @@ qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
"s:device", device,
"s:target", file,
"U:speed", speed,
+ "z:granularity", granularity,
+ "z:buf-size", buf_size,
z is for signed values. both are unsigned. I think you wanted to use a
'p' formatter.
"s:sync", shallow ?
"top" : "full",
"s:mode", reuse ? "existing" :
"absolute-paths",
"S:format", format,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index d8c9308..cd331db 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -249,6 +249,8 @@ int qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
const char *file,
const char *format,
unsigned long long speed,
+ unsigned int granularity,
+ unsigned int buf_size,
unsigned int flags)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONDrivePivot(qemuMonitorPtr mon,
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index e3fb4f7..afbf13a 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1176,7 +1176,7 @@ GEN_TEST_FUNC(qemuMonitorJSONRemoveNetdev, "net0")
GEN_TEST_FUNC(qemuMonitorJSONDelDevice, "ide0")
GEN_TEST_FUNC(qemuMonitorJSONAddDevice, "some_dummy_devicestr")
GEN_TEST_FUNC(qemuMonitorJSONSetDrivePassphrase, "vda",
"secret_passhprase")
-GEN_TEST_FUNC(qemuMonitorJSONDriveMirror, "vdb", "/foo/bar", NULL,
1024,
+GEN_TEST_FUNC(qemuMonitorJSONDriveMirror, "vdb", "/foo/bar", NULL,
1024, 0, 0,
VIR_DOMAIN_BLOCK_REBASE_SHALLOW | VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)
GEN_TEST_FUNC(qemuMonitorJSONBlockCommit, "vdb", "/foo/bar1",
"/foo/bar2", NULL, 1024)
GEN_TEST_FUNC(qemuMonitorJSONDrivePivot, "vdb", NULL, NULL)
There are a few singedness problems in this patch. Although trivial
enough to grant an
ACK if you fix the issues above.
Peter