Re: [PATCH v2 14/15] qemu: migration: Migrate block dirty bitmaps corresponding to checkpoints

2021-02-19 Thread Jiri Denemark
On Fri, Feb 19, 2021 at 12:58:26 +0100, Peter Krempa wrote:
> Preserve block dirty bitmaps after migration with
> QEMU_MONITOR_MIGRATE_NON_SHARED_(DISK|INC).
> 
> This patch implements functions which offer the bitmaps to the
> destination, check for eligibility on destination and then configure
> source for the migration.
> 
> Signed-off-by: Peter Krempa 
> ---
>  src/qemu/qemu_migration.c | 333 +-
>  1 file changed, 331 insertions(+), 2 deletions(-)

Reviewed-by: Jiri Denemark 



[PATCH v2 14/15] qemu: migration: Migrate block dirty bitmaps corresponding to checkpoints

2021-02-19 Thread Peter Krempa
Preserve block dirty bitmaps after migration with
QEMU_MONITOR_MIGRATE_NON_SHARED_(DISK|INC).

This patch implements functions which offer the bitmaps to the
destination, check for eligibility on destination and then configure
source for the migration.

Signed-off-by: Peter Krempa 
---
 src/qemu/qemu_migration.c | 333 +-
 1 file changed, 331 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 4e69fab384..08f60c6db3 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2205,6 +2205,91 @@ qemuMigrationSrcCleanup(virDomainObjPtr vm,
 }


+/**
+ * qemuMigrationSrcBeginPhaseBlockDirtyBitmaps:
+ * @mig: migration cookie struct
+ * @vm: domain object
+ * @migrate_disks: disks which are being migrated
+ * @nmigrage_disks: number of @migrate_disks
+ *
+ * Enumerates block dirty bitmaps on disks which will undergo storage migration
+ * and fills them into @mig to be offered to the destination.
+ */
+static int
+qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(qemuMigrationCookiePtr mig,
+virDomainObjPtr vm,
+const char **migrate_disks,
+size_t nmigrate_disks)
+
+{
+GSList *disks = NULL;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+size_t i;
+
+g_autoptr(GHashTable) blockNamedNodeData = NULL;
+
+if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, 
priv->job.asyncJob)))
+return -1;
+
+for (i = 0; i < vm->def->ndisks; i++) {
+qemuMigrationBlockDirtyBitmapsDiskPtr disk;
+GSList *bitmaps = NULL;
+virDomainDiskDefPtr diskdef = vm->def->disks[i];
+qemuBlockNamedNodeDataPtr nodedata = virHashLookup(blockNamedNodeData, 
diskdef->src->nodeformat);
+size_t j;
+
+if (!nodedata)
+continue;
+
+if (migrate_disks) {
+bool migrating = false;
+
+for (j = 0; j < nmigrate_disks; j++) {
+if (STREQ(migrate_disks[j], diskdef->dst)) {
+migrating = true;
+break;
+}
+}
+
+if (!migrating)
+continue;
+}
+
+for (j = 0; j < nodedata->nbitmaps; j++) {
+qemuMigrationBlockDirtyBitmapsDiskBitmapPtr bitmap;
+
+if (!qemuBlockBitmapChainIsValid(diskdef->src,
+ nodedata->bitmaps[j]->name,
+ blockNamedNodeData))
+continue;
+
+bitmap = g_new0(qemuMigrationBlockDirtyBitmapsDiskBitmap, 1);
+bitmap->bitmapname = g_strdup(nodedata->bitmaps[j]->name);
+bitmap->alias = g_strdup_printf("libvirt-%s-%s",
+diskdef->dst,
+nodedata->bitmaps[j]->name);
+bitmaps = g_slist_prepend(bitmaps, bitmap);
+}
+
+if (!bitmaps)
+continue;
+
+disk = g_new0(qemuMigrationBlockDirtyBitmapsDisk, 1);
+disk->target = g_strdup(diskdef->dst);
+disk->bitmaps = bitmaps;
+disks = g_slist_prepend(disks, disk);
+}
+
+if (!disks)
+return 0;
+
+mig->blockDirtyBitmaps = disks;
+mig->flags |= QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
+
+return 0;
+}
+
+
 /* The caller is supposed to lock the vm and start a migration job. */
 static char *
 qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver,
@@ -2317,6 +2402,12 @@ qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver,
 if (!(mig = qemuMigrationCookieNew(vm->def, priv->origname)))
 return NULL;

+if (cookieFlags & QEMU_MIGRATION_COOKIE_NBD &&
+virQEMUCapsGet(priv->qemuCaps, 
QEMU_CAPS_MIGRATION_PARAM_BLOCK_BITMAP_MAPPING) &&
+qemuMigrationSrcBeginPhaseBlockDirtyBitmaps(mig, vm, migrate_disks,
+nmigrate_disks) < 0)
+return NULL;
+
 if (qemuMigrationCookieFormat(mig, driver, vm,
   QEMU_MIGRATION_SOURCE,
   cookieout, cookieoutlen,
@@ -2530,6 +2621,92 @@ qemuMigrationDstPrepare(virDomainObjPtr vm,
  migrateFrom, fd, NULL);
 }

+
+/**
+ * qemuMigrationDstPrepareAnyBlockDirtyBitmaps:
+ * @vm: domain object
+ * @mig: migration cookie
+ * @migParams: migration parameters
+ * @flags: migration flags
+ *
+ * Checks whether block dirty bitmaps offered by the migration source are
+ * to be migrated (e.g. they don't exist, the destination is compatible etc)
+ * and sets up destination qemu for migrating the bitmaps as well as updates 
the
+ * list of eligible bitmaps in the migration cookie to be sent back to the
+ * source.
+ */
+static int
+qemuMigrationDstPrepareAnyBlockDirtyBitmaps(virDomainObjPtr vm,
+