Wire up all the pieces in the previous patches to actually enable
a block copy job.
This compiles, but isn't correct, and there are still more patches
to go:
prereq patch: fix qemuDomainBlockJobImpl to do BLOCK_JOB_PULL and
BLOCK_JOB_SPEED in one monitor job, rather than two
this patch: fix things to reuse the same block job for all three
monitor calls (drive-mirror, block_stream, block_job_set_speed);
handle errors better, set SELinux labels and lock manager usage
properly, add a disk audit message
future patch 1: add block job abort processing, which calls
'drive-reopen' at the proper times, and also includes SELinux
and lock manager activity
future patch 2: wire up the _SHALLOW flag to use 'query-block'
to determine the appropriate 'base' argument for shallow copy
future patch 3: wire up the virDomainBlockCopy command to this
function
future patch 4: RHEL-only: cater to the __com.redhat_* naming
prefix of an early backport
what else? probably several cleanup patches
But the series is progressing nicely, and even though this
particular patch isn't ready, the prereqs can be reviewed.
* src/qemu/qemu_driver.c (qemuDomainBlockCopy): New function.
(qemuDomainBlockRebase): Call it when appropriate.
---
src/qemu/qemu_driver.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 107 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1664e14..42af95e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11769,12 +11769,117 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
}
static int
+qemuDomainBlockCopy(virDomainPtr dom, const char *path, const char *base,
+ const char *dest, const char *format,
+ unsigned long bandwidth, unsigned int flags)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ qemuDomainObjPrivatePtr priv;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *device = NULL;
+ virDomainDiskDefPtr disk;
+ int ret = -1;
+ int idx;
+ virJSONValuePtr actions = NULL;
+
+ /* Step 0: get the disk, check for caps */
+ virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);
+
+ qemuDriverLock(driver);
+ virUUIDFormat(dom->uuid, uuidstr);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ qemuReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"),
uuidstr);
+ goto cleanup;
+ }
+
+ device = qemuDiskPathToAlias(vm, path, &idx);
+ if (!device) {
+ goto cleanup;
+ }
+ disk = vm->def->disks[idx];
+ if (disk->mirror) {
+ qemuReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
+ _("disk '%s' already in active block copy
job"),
+ disk->dst);
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+ if (!(qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
+ qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_REOPEN))) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("block copy is not supported with this QEMU
binary"));
+ goto cleanup;
+ }
+ if (vm->persistent) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not transient"));
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto endjob;
+ }
+
+ /* Step 1: call 'drive-mirror' to start the mirroring */
+ actions = virJSONValueNewArray();
+ if (!actions) {
+ virReportOOMError();
+ goto endjob;
+ }
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorDriveMirror(priv->mon, actions, device, dest,
+ format ? format : disk->driverType,
+ (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT ?
+ QEMU_MONITOR_DRIVE_MIRROR_EXISTING :
+ QEMU_MONITOR_DRIVE_MIRROR_ABSOLUTE));
+
+ if (ret == 0)
+ ret = qemuMonitorTransaction(priv->mon, actions);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ /* Step 2: call 'block_stream' to pull into the mirror */
+ ret = qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
+ BLOCK_JOB_PULL, flags);
+ if (ret == 0 && bandwidth != 0)
+ ret = qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
+ BLOCK_JOB_SPEED, flags);
+
+endjob:
+ if (qemuDomainObjEndJob(driver, vm) == 0) {
+ vm = NULL;
+ goto cleanup;
+ }
+
+cleanup:
+ VIR_FREE(device);
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
+static int
qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
unsigned long bandwidth, unsigned int flags)
{
int ret;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_COPY |
+ VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);
+
+ if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY)
+ return qemuDomainBlockCopy(dom, path, NULL, base, NULL, bandwidth,
+ flags & ~VIR_DOMAIN_BLOCK_REBASE_COPY);
+
ret = qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
BLOCK_JOB_PULL, flags);
if (ret == 0 && bandwidth != 0)
@@ -11787,6 +11892,7 @@ static int
qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
unsigned int flags)
{
+ virCheckFlags(0, -1);
return qemuDomainBlockRebase(dom, path, NULL, bandwidth, flags);
}
--
1.7.7.6