On Thu, Feb 21, 2013 at 14:39:24 +0100, Michal Privoznik wrote:
This function does the source part of NBD magic. It
invokes drive-mirror on each non shared and RW disk with
a source and wait till the mirroring process completes.
When it does we can proceed with migration.
Currently, an active waiting is done: every 500ms libvirt
asks qemu if block-job is finished or not. However, once
the job finishes, qemu doesn't report its progress so we
can only assume if the job finished successfully or not.
The better solution would be to listen to the event which
is sent as soon as the job finishes. The event does
contain the result of job.
...
+static int
+qemuMigrationDriveMirror(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuMigrationCookiePtr mig,
+ const char *host,
+ unsigned long speed,
+ unsigned int *migrate_flags)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret = -1;
+ int mon_ret;
+ int port;
+ size_t i, lastGood = 0;
+ char *diskAlias = NULL;
+ char *nbd_dest = NULL;
+ unsigned int mirror_flags = VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT;
+ virErrorPtr err = NULL;
+
+ if (!(*migrate_flags & (QEMU_MONITOR_MIGRATE_NON_SHARED_DISK |
+ QEMU_MONITOR_MIGRATE_NON_SHARED_INC)))
+ return 0;
+
+ if (!mig->nbd) {
+ /* Destination doesn't support NBD server.
+ * Fall back to previous implementation. */
+ VIR_DEBUG("Destination doesn't support NBD server "
+ "Falling back to previous implementation.");
+ return 0;
+ }
+
+ /* steal NBD port and thus prevent its propagation back to destination */
+ port = mig->nbd->port;
+ mig->nbd->port = 0;
+
+ if (*migrate_flags & QEMU_MONITOR_MIGRATE_NON_SHARED_INC)
+ mirror_flags |= VIR_DOMAIN_BLOCK_REBASE_SHALLOW;
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+ virDomainBlockJobInfo info;
+
+ /* skip shared, RO and source-less disks */
+ if (disk->shared || disk->readonly || !disk->src)
+ continue;
+
+ VIR_FREE(diskAlias);
+ VIR_FREE(nbd_dest);
+ if ((virAsprintf(&diskAlias, "%s%s",
+ QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) ||
+ (virAsprintf(&nbd_dest, "nbd:%s:%u:exportname=%s",
+ host, port, diskAlias) < 0)) {
port is signed => s/%u/%d/
ACK
Jirka