[libvirt] [PATCH 3/3] qemu: Forbid migration with cache != none

Jiri Denemark jdenemar at redhat.com
Tue Feb 21 16:17:23 UTC 2012


Migrating domains with disks using cache != none is unsafe unless the
disk images are stored on coherent clustered filesystem. Thus we forbid
migrating such domains unless VIR_MIGRATE_UNSAFE flags is used.
---
 src/qemu/qemu_driver.c    |    3 ++-
 src/qemu/qemu_migration.c |   36 ++++++++++++++++++++++++++++++++----
 src/qemu/qemu_migration.h |    6 ++++--
 3 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 717bdf1..63a0703 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8767,7 +8767,8 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
         goto endjob;
 
     if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname,
-                                   cookieout, cookieoutlen)))
+                                   cookieout, cookieoutlen,
+                                   flags)))
         goto endjob;
 
     if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index f0af494..127b35c 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -817,6 +817,27 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm,
     return true;
 }
 
+static bool
+qemuMigrationIsSafe(virDomainDefPtr def)
+{
+    int i;
+
+    for (i = 0 ; i < def->ndisks ; i++) {
+        virDomainDiskDefPtr disk = def->disks[i];
+
+        /* shared && !readonly implies cache=none */
+        if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE &&
+            (disk->cachemode || !disk->shared || disk->readonly)) {
+            qemuReportError(VIR_ERR_MIGRATE_UNSAFE, "%s",
+                            _("Migration may lead to data corruption if disks"
+                              " use cache != none"));
+            return false;
+        }
+    }
+
+    return true;
+}
+
 /** qemuMigrationSetOffline
  * Pause domain for non-live migration.
  */
@@ -1010,7 +1031,8 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
                          const char *xmlin,
                          const char *dname,
                          char **cookieout,
-                         int *cookieoutlen)
+                         int *cookieoutlen,
+                         unsigned long flags)
 {
     char *rv = NULL;
     qemuMigrationCookiePtr mig = NULL;
@@ -1018,9 +1040,9 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
 
     VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
-              " cookieout=%p, cookieoutlen=%p",
+              " cookieout=%p, cookieoutlen=%p, flags=%lx",
               driver, vm, NULLSTR(xmlin), NULLSTR(dname),
-              cookieout, cookieoutlen);
+              cookieout, cookieoutlen, flags);
 
     /* Only set the phase if we are inside QEMU_ASYNC_JOB_MIGRATION_OUT.
      * Otherwise we will start the async job later in the perform phase losing
@@ -1032,6 +1054,9 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
     if (!qemuMigrationIsAllowed(driver, vm, NULL))
         goto cleanup;
 
+    if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
+        goto cleanup;
+
     if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0)))
         goto cleanup;
 
@@ -2070,7 +2095,7 @@ static int doPeer2PeerMigrate3(struct qemud_driver *driver,
      * a single job.  */
 
     dom_xml = qemuMigrationBegin(driver, vm, xmlin, dname,
-                                 &cookieout, &cookieoutlen);
+                                 &cookieout, &cookieoutlen, flags);
     if (!dom_xml)
         goto cleanup;
 
@@ -2354,6 +2379,9 @@ qemuMigrationPerformJob(struct qemud_driver *driver,
     if (!qemuMigrationIsAllowed(driver, vm, NULL))
         goto cleanup;
 
+    if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
+        goto cleanup;
+
     resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
 
     if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index f806ca1..41e4eac 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -35,7 +35,8 @@
      VIR_MIGRATE_PAUSED |                       \
      VIR_MIGRATE_NON_SHARED_DISK |              \
      VIR_MIGRATE_NON_SHARED_INC |               \
-     VIR_MIGRATE_CHANGE_PROTECTION)
+     VIR_MIGRATE_CHANGE_PROTECTION |            \
+     VIR_MIGRATE_UNSAFE)
 
 enum qemuMigrationJobPhase {
     QEMU_MIGRATION_PHASE_NONE = 0,
@@ -81,7 +82,8 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
                          const char *xmlin,
                          const char *dname,
                          char **cookieout,
-                         int *cookieoutlen);
+                         int *cookieoutlen,
+                         unsigned long flags);
 
 int qemuMigrationPrepareTunnel(struct qemud_driver *driver,
                                virConnectPtr dconn,
-- 
1.7.8.4




More information about the libvir-list mailing list