]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Forbid migration with cache != none
authorJiri Denemark <jdenemar@redhat.com>
Tue, 21 Feb 2012 12:20:06 +0000 (13:20 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Thu, 23 Feb 2012 13:34:56 +0000 (14:34 +0100)
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
src/qemu/qemu_migration.c
src/qemu/qemu_migration.h

index 717bdf12439dcabf708989e9ea5d6f9906f5ec44..63a070311ca98e22fb81ef7421ed05e4f78fd886 100644 (file)
@@ -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)) {
index f0af49417aef24181b00a6a59c6d7ee55ec3eb02..3f50136e26ef309daa86c36dcaf1dcc214f8c8a0 100644 (file)
@@ -45,6 +45,7 @@
 #include "virtime.h"
 #include "locking/domain_lock.h"
 #include "rpc/virnetsocket.h"
+#include "storage_file.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -817,6 +818,34 @@ 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->src &&
+            disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE &&
+            (disk->cachemode || !disk->shared || disk->readonly)) {
+            int cfs;
+            if ((cfs = virStorageFileIsClusterFS(disk->src)) == 1)
+                continue;
+            else if (cfs < 0)
+                return false;
+
+            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 +1039,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 +1048,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 +1062,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 +2103,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 +2387,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))) {
index f806ca1be684307b6eb5dd483a22dfa4c8b55a2c..41e4eac9dddf9191db8aafa6cf3b96958ef10446 100644 (file)
@@ -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,