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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list