RHEL-only drive-mirror and drive-reopen are still under upstream qemu discussion; as a result, RHEL decided to backport things under a downstream name. Accommodate these differences. There are a few differences between the upstream proposal[1] and the RHEL build. The RHEL build uses the __com.redhat_ prefix to make the differences obvious. Upstream has a mandatory 'full' argument for 'drive-mirror', and 'drive-mirror' cannot be used as part of a transaction (that is, upstream only supports streaming block copy). Downstream treates 'full' as optional (defaulting to false), and can combine 'blockdev-snapshot-sync' and 'drive-mirror' in a single 'transaction' in order to support snapshot+mirror in addition to streaming block copy. [1]https://lists.gnu.org/archive/html/qemu-devel/2012-04/msg01630.html I don't think it's worth trying to support both spellings at once: if you build upstream libvirt on RHEL, you lose out on the ability to control the RHEL-specific block copy naming, but then you are also capable of building upstream qemu to get the upstream spelling of the same feature (that is, if you use RHEL, you should either stick to the distro patches across the entire virt stack, or you are assumed to be capable of building the entire virt stack yourself). * src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Check for alternate spelling. (qemuMonitorJSONDriveReopen): Use that spelling. (qemuMonitorJSONDriveMirror): Likewise, and add an argument for snapshot+mirror. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror): Update. * src/qemu/qemu_monitor.c (qemuMonitorDriveMirror): Likewise. * src/qemu/qemu_monitor.h (qemuMonitorDriveMirror): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockCopy): Likewise. --- was 15/18 in v4 v5: a lot more invasive, now that qemu 1.1 has a firmer proposal that differs from RHEL's desire to still provide snapshot+mirror mode in contrast to streaming mirror mode. src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_monitor.c | 9 +++--- src/qemu/qemu_monitor.h | 3 +- src/qemu/qemu_monitor_json.c | 57 +++++++++++++++++++++++++++++++----------- src/qemu/qemu_monitor_json.h | 3 +- 5 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a27f6c2..dd49cb9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -12055,7 +12055,7 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path, /* Actually start the mirroring */ qemuDomainObjEnterMonitorWithDriver(driver, vm); - ret = qemuMonitorDriveMirror(priv->mon, device, dest, format, flags); + ret = qemuMonitorDriveMirror(priv->mon, NULL, device, dest, format, flags); virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0); if (ret == 0 && bandwidth != 0) { /* Setting speed now is best-effort. */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 34c7926..6a050e1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2687,14 +2687,14 @@ qemuMonitorDiskSnapshot(qemuMonitorPtr mon, virJSONValuePtr actions, /* Add the drive-mirror action to a transaction. */ int -qemuMonitorDriveMirror(qemuMonitorPtr mon, +qemuMonitorDriveMirror(qemuMonitorPtr mon, virJSONValuePtr actions, const char *device, const char *file, const char *format, unsigned int flags) { int ret = -1; - VIR_DEBUG("mon=%p, device=%s, file=%s, format=%s, flags=%x", - mon, device, file, format, flags); + VIR_DEBUG("mon=%p, actions=%p, device=%s, file=%s, format=%s, flags=%x", + mon, actions, device, file, format, flags); if (!mon) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", @@ -2703,7 +2703,8 @@ qemuMonitorDriveMirror(qemuMonitorPtr mon, } if (mon->json) - ret = qemuMonitorJSONDriveMirror(mon, device, file, format, flags); + ret = qemuMonitorJSONDriveMirror(mon, actions, device, file, format, + flags); else qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("drive-mirror requires JSON monitor")); diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 1b4b130..c8a834b 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -511,11 +511,12 @@ int qemuMonitorDiskSnapshot(qemuMonitorPtr mon, int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int qemuMonitorDriveMirror(qemuMonitorPtr mon, + virJSONValuePtr actions, const char *device, const char *file, const char *format, unsigned int flags) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); int qemuMonitorDriveReopen(qemuMonitorPtr mon, const char *device, const char *file, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 6bce701..8ff1501 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -989,9 +989,9 @@ qemuMonitorJSONCheckCommands(qemuMonitorPtr mon, qemuCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_SYNC); else if (STREQ(name, "block-job-cancel")) qemuCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC); - else if (STREQ(name, "drive-mirror")) + else if (STREQ(name, "__com.redhat_drive-mirror")) qemuCapsSet(qemuCaps, QEMU_CAPS_DRIVE_MIRROR); - else if (STREQ(name, "drive-reopen")) + else if (STREQ(name, "__com.redhat_drive-reopen")) qemuCapsSet(qemuCaps, QEMU_CAPS_DRIVE_REOPEN); } @@ -3205,7 +3205,7 @@ cleanup: } int -qemuMonitorJSONDriveMirror(qemuMonitorPtr mon, +qemuMonitorJSONDriveMirror(qemuMonitorPtr mon, virJSONValuePtr actions, const char *device, const char *file, const char *format, unsigned int flags) { @@ -3215,20 +3215,47 @@ qemuMonitorJSONDriveMirror(qemuMonitorPtr mon, bool shallow = (flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) != 0; bool reuse = (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) != 0; - cmd = qemuMonitorJSONMakeCommand("drive-mirror", - "s:device", device, - "s:target", file, - "b:full", !shallow, - "s:mode", - reuse ? "existing" : "absolute-paths", - format ? "s:format" : NULL, format, - NULL); + /* In the RHEL build, '__com.redhat_drive-mirror' is also a part + * of 'transaction', but when used there, the 'full' argument must + * not be given; as a result, the standalone command made 'full' + * optional, defaulting to false. */ + if (actions && !shallow) + return -1; + if (shallow) { + cmd = qemuMonitorJSONMakeCommandRaw(actions != NULL, + "__com.redhat_drive-mirror", + "s:device", device, + "s:target", file, + "s:mode", + reuse ? "existing" : "absolute-paths", + format ? "s:format" : NULL, format, + NULL); + } else { + cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive-mirror", + "s:device", device, + "s:target", file, + "b:full", true, + "s:mode", + reuse ? "existing" : "absolute-paths", + format ? "s:format" : NULL, format, + NULL); + } + if (!cmd) return -1; - if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0) - goto cleanup; - ret = qemuMonitorJSONCheckError(cmd, reply); + if (actions) { + if (virJSONValueArrayAppend(actions, cmd) < 0) { + virReportOOMError(); + } else { + cmd = NULL; + ret = 0; + } + } else { + if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0) + goto cleanup; + ret = qemuMonitorJSONCheckError(cmd, reply); + } cleanup: virJSONValueFree(cmd); @@ -3272,7 +3299,7 @@ qemuMonitorJSONDriveReopen(qemuMonitorPtr mon, const char *device, virJSONValuePtr cmd; virJSONValuePtr reply = NULL; - cmd = qemuMonitorJSONMakeCommand("drive-reopen", + cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive-reopen", "s:device", device, "s:new-image-file", file, format ? "s:format" : NULL, format, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index d93c37d..6306e99 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -236,11 +236,12 @@ int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon, int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int qemuMonitorJSONDriveMirror(qemuMonitorPtr mon, + virJSONValuePtr actions, const char *device, const char *file, const char *format, unsigned int flags) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); int qemuMonitorJSONDriveReopen(qemuMonitorPtr mon, const char *device, const char *file, -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list