Re: [libvirt] [PATCHv5 11/23] blockjob: implement block copy for qemu

2012-04-19 Thread Jiri Denemark
On Mon, Apr 16, 2012 at 23:06:02 -0600, Eric Blake wrote:
 Minimal patch to wire up all the pieces in the previous patches
 to actually enable a block copy job.  By minimal, I mean that
 qemu creates the file (that is, no REUSE_EXT flag support yet),
 SELinux must be disabled, a lock manager is not informed, and
 the audit logs aren't updated.  But those will be added as
 improvements in future patches.
 
 * src/qemu/qemu_driver.c (qemuDomainBlockCopy): New function.
 (qemuDomainBlockRebase): Call it when appropriate.
 ---
 
 was 12/18 in v4
 v5: address review comments, add comment in code

OK

Jirka

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv5 11/23] blockjob: implement block copy for qemu

2012-04-16 Thread Eric Blake
Minimal patch to wire up all the pieces in the previous patches
to actually enable a block copy job.  By minimal, I mean that
qemu creates the file (that is, no REUSE_EXT flag support yet),
SELinux must be disabled, a lock manager is not informed, and
the audit logs aren't updated.  But those will be added as
improvements in future patches.

* src/qemu/qemu_driver.c (qemuDomainBlockCopy): New function.
(qemuDomainBlockRebase): Call it when appropriate.
---

was 12/18 in v4
v5: address review comments, add comment in code

 src/qemu/qemu_driver.c |  122 +++-
 1 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8b6c984..5c3cea8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11910,10 +11910,126 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const 
char *path,
 }

 static int
+qemuDomainBlockCopy(virDomainPtr dom, const char *path,
+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;
+
+/* Preliminaries: find the disk we are editing, sanity checks */
+virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW, -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) 
+  qemuCapsGet(priv-qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
+qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s,
+_(block copy is not supported with this QEMU 
binary));
+goto cleanup;
+}
+if (vm-persistent) {
+/* XXX if qemu ever lets us start a new domain with mirroring
+ * already active, we can relax this; but for now, the risk of
+ * 'managedsave' due to libvirt-guests means we can't risk
+ * this on persistent domains.  */
+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;
+}
+
+/* Prepare the destination file.  */
+/* XXX We also need to add security labeling, lock manager lease,
+ * and auditing of those events, as well as to support reuse of
+ * existing images, including probing the existing format of an
+ * existing image.  */
+if (!format)
+format = disk-driverType;
+if ((format  !(disk-mirrorFormat = strdup(format))) ||
+!(disk-mirror = strdup(dest))) {
+virReportOOMError();
+goto endjob;
+}
+
+/* Actually start the mirroring */
+qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ret = qemuMonitorDriveMirror(priv-mon, device, dest, format, flags);
+if (ret == 0  bandwidth != 0)
+ret = qemuMonitorBlockJob(priv-mon, device, NULL, bandwidth, NULL,
+  BLOCK_JOB_SPEED_INTERNAL, true);
+qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+endjob:
+if (ret  0) {
+VIR_FREE(disk-mirror);
+VIR_FREE(disk-mirrorFormat);
+}
+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)
 {
-virCheckFlags(0, -1);
+virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+  VIR_DOMAIN_BLOCK_REBASE_COPY |
+  VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1);
+
+if (flags  VIR_DOMAIN_BLOCK_REBASE_COPY) {
+const char *format = NULL;
+if (flags  VIR_DOMAIN_BLOCK_REBASE_COPY_RAW)
+format = raw;
+flags =