File libvirt-migration-Make-erroring-out-on-I-O-error-controllable-by-flag.patch of Package libvirt

From 25b95e62905d6b6ae63e84d934f5f9c3d89ec134 Mon Sep 17 00:00:00 2001
Message-Id: <25b95e62905d6b6ae63e84d934f5f9c3d89ec134.1373885147.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 4 Jul 2013 11:50:23 +0200
Subject: [PATCH] migration: Make erroring out on I/O error controllable by
 flag

https://bugzilla.redhat.com/show_bug.cgi?id=972675

Paolo Bonzini pointed out that it's actually possible to migrate a qemu
instance that was paused due to I/O error and it will be able to work on
the destination if the storage is accessible.

This patch introduces flag VIR_MIGRATE_ABORT_ON_ERROR that cancels the
migration in case an I/O error happens while it's being performed and
allows migration without this flag. This flag can be possibly used for
other error reasons that may be introduced in the future.
(cherry picked from commit cf6d56ac433273b7e4e087bb861ebced0680cec3)

Conflicts:
	include/libvirt/libvirt.h.in - XBZRLE and offline migration not
                                   backported

	src/qemu/qemu_driver.c - 98e92ba83b7ed01515d7243a0012f4571800027b,
                             08379dbd45c2078b0e5641e625f250370d5ddd11
                             not backported

	src/qemu/qemu_migration.c - qemu driver struct renaming not
                                backported

	src/qemu/qemu_migration.h - XBZRLE and offline migration not
                                backported

	tools/virsh-domain.c - conversion to c99 struct init not backported

	tools/virsh.pod - XBZRLE docs missing
---
 include/libvirt/libvirt.h.in |  1 +
 src/qemu/qemu_migration.c    | 22 +++++++++++++---------
 src/qemu/qemu_migration.h    |  6 ++++--
 tools/virsh-domain.c         |  7 +++++++
 tools/virsh.pod              |  5 ++++-
 5 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index f91ffeb..0264a93 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1006,6 +1006,7 @@ typedef enum {
                                                * whole migration process; this will be used automatically
                                                * when supported */
     VIR_MIGRATE_UNSAFE            = (1 << 9), /* force migration even if it is considered unsafe */
+    VIR_MIGRATE_ABORT_ON_ERROR    = (1 << 12), /* abort migration on I/O errors happened during migration */
 } virDomainMigrateFlags;
 
 /* Domain migration. */
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 064bba0..cf90eae 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -803,7 +803,7 @@ error:
  * the fact that older servers did not do checks on the source. */
 bool
 qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm,
-                       virDomainDefPtr def, bool remote)
+                       virDomainDefPtr def, bool remote, bool abort_on_error)
 {
     int nsnapshots;
     int pauseReason;
@@ -831,7 +831,8 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm,
             }
 
             /* cancel migration if disk I/O error is emitted while migrating */
-            if (virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
+            if (abort_on_error &&
+                virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
                 pauseReason == VIR_DOMAIN_PAUSED_IOERROR) {
                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                _("cannot migrate domain with I/O error"));
@@ -1047,7 +1048,7 @@ qemuMigrationUpdateJobStatus(struct qemud_driver *driver,
 static int
 qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm,
                                enum qemuDomainAsyncJob asyncJob,
-                               virConnectPtr dconn)
+                               virConnectPtr dconn, bool abort_on_error)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     const char *job;
@@ -1074,7 +1075,7 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm,
         struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
 
         /* cancel migration if disk I/O error is emitted while migrating */
-        if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT &&
+        if (abort_on_error &&
             virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
             pauseReason == VIR_DOMAIN_PAUSED_IOERROR)
             goto cancel;
@@ -1238,6 +1239,7 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
     qemuMigrationCookiePtr mig = NULL;
     virDomainDefPtr def = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
               " cookieout=%p, cookieoutlen=%p, flags=%lx",
@@ -1251,7 +1253,7 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
     if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT)
         qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_BEGIN3);
 
-    if (!qemuMigrationIsAllowed(driver, vm, NULL, true))
+    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
         goto cleanup;
 
     if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
@@ -1346,7 +1348,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
                                         VIR_DOMAIN_XML_INACTIVE)))
         goto cleanup;
 
-    if (!qemuMigrationIsAllowed(driver, NULL, def, true))
+    if (!qemuMigrationIsAllowed(driver, NULL, def, true, false))
         goto cleanup;
 
     /* Target domain name, maybe renamed. */
@@ -2010,6 +2012,7 @@ qemuMigrationRun(struct qemud_driver *driver,
     int fd = -1;
     unsigned long migrate_speed = resource ? resource : priv->migMaxBandwidth;
     virErrorPtr orig_err = NULL;
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
               "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
@@ -2145,7 +2148,7 @@ qemuMigrationRun(struct qemud_driver *driver,
 
     if (qemuMigrationWaitForCompletion(driver, vm,
                                        QEMU_ASYNC_JOB_MIGRATION_OUT,
-                                       dconn) < 0)
+                                       dconn, abort_on_error) < 0)
         goto cleanup;
 
     /* When migration completed, QEMU will have paused the
@@ -2793,6 +2796,7 @@ qemuMigrationPerformJob(struct qemud_driver *driver,
     int ret = -1;
     int resume = 0;
     virErrorPtr orig_err = NULL;
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
         goto cleanup;
@@ -2803,7 +2807,7 @@ qemuMigrationPerformJob(struct qemud_driver *driver,
         goto endjob;
     }
 
-    if (!qemuMigrationIsAllowed(driver, vm, NULL, true))
+    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
         goto endjob;
 
     if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
@@ -3475,7 +3479,7 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm,
     if (rc < 0)
         goto cleanup;
 
-    rc = qemuMigrationWaitForCompletion(driver, vm, asyncJob, NULL);
+    rc = qemuMigrationWaitForCompletion(driver, vm, asyncJob, NULL, false);
 
     if (rc < 0)
         goto cleanup;
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 2390e04..9927d08 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -36,7 +36,8 @@
      VIR_MIGRATE_NON_SHARED_DISK |              \
      VIR_MIGRATE_NON_SHARED_INC |               \
      VIR_MIGRATE_CHANGE_PROTECTION |            \
-     VIR_MIGRATE_UNSAFE)
+     VIR_MIGRATE_UNSAFE |                       \
+     VIR_MIGRATE_ABORT_ON_ERROR)
 
 enum qemuMigrationJobPhase {
     QEMU_MIGRATION_PHASE_NONE = 0,
@@ -145,7 +146,8 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
                          int retcode);
 
 bool qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm,
-                            virDomainDefPtr def, bool remote);
+                            virDomainDefPtr def, bool remote,
+                            bool abort_on_error);
 
 int qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm,
                         int fd, off_t offset, const char *path,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8f2e4d2..f94f609 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -6696,6 +6696,10 @@ static const vshCmdOptDef opts_migrate[] = {
     {"dname", VSH_OT_DATA, 0, N_("rename to new name during migration (if supported)")},
     {"timeout", VSH_OT_INT, 0, N_("force guest to suspend if live migration exceeds timeout (in seconds)")},
     {"xml", VSH_OT_STRING, 0, N_("filename containing updated XML for the target")},
+    {.name = "abort-on-error",
+     .type = VSH_OT_BOOL,
+     .help = N_("abort on soft errors during migration")
+    },
     {NULL, 0, 0, NULL}
 };
 
@@ -6762,6 +6766,9 @@ doMigrate(void *opaque)
     if (vshCommandOptBool(cmd, "unsafe"))
         flags |= VIR_MIGRATE_UNSAFE;
 
+    if (vshCommandOptBool(cmd, "abort-on-error"))
+        flags |= VIR_MIGRATE_ABORT_ON_ERROR;
+
     if (xmlfile &&
         virFileReadAll(xmlfile, 8192, &xml) < 0) {
         vshError(ctl, _("file '%s' doesn't exist"), xmlfile);
diff --git a/tools/virsh.pod b/tools/virsh.pod
index d9626b1..32aa742 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1024,6 +1024,7 @@ stats.
 =item B<migrate> [I<--live>] [I<--direct>] [I<--p2p> [I<--tunnelled>]]
 [I<--persistent>] [I<--undefinesource>] [I<--suspend>] [I<--copy-storage-all>]
 [I<--copy-storage-inc>] [I<--change-protection>] [I<--unsafe>] [I<--verbose>]
+[I<--abort-on-error>]
 I<domain> I<desturi> [I<migrateuri>] [I<dname>]
 [I<--timeout> B<seconds>] [I<--xml> B<file>]
 
@@ -1042,7 +1043,9 @@ host. I<--change-protection> enforces that no incompatible configuration
 changes will be made to the domain while the migration is underway; this flag
 is implicitly enabled when supported by the hypervisor, but can be explicitly
 used to reject the migration if the hypervisor lacks change protection
-support.  I<--verbose> displays the progress of migration.
+support.  I<--verbose> displays the progress of migration.  I<--abort-on-error>
+cancels the migration if a soft error (for example I/O error) happens during
+the migration.
 
 B<Note>: Individual hypervisors usually do not support all possible types of
 migration. For example, QEMU does not support direct migration.
-- 
1.8.3.2

openSUSE Build Service is sponsored by