[libvirt] [PATCH v3 REBASE 2/2] qemu: report drive mirror errors on migration

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Fri Sep 8 07:59:43 UTC 2017


---
 src/qemu/qemu_blockjob.c  | 14 +++++++++---
 src/qemu/qemu_blockjob.h  |  3 ++-
 src/qemu/qemu_driver.c    |  4 ++--
 src/qemu/qemu_migration.c | 55 +++++++++++++++++++++++++++++++++--------------
 4 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index cb00736..5e4fe6d 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -47,6 +47,7 @@ VIR_LOG_INIT("qemu.qemu_blockjob");
  * @driver: qemu driver
  * @vm: domain
  * @disk: domain disk
+ * @error: error (output parameter)
  *
  * Update disk's mirror state in response to a block job event stored in
  * blockJobStatus by qemuProcessHandleBlockJob event handler.
@@ -57,17 +58,24 @@ int
 qemuBlockJobUpdate(virQEMUDriverPtr driver,
                    virDomainObjPtr vm,
                    qemuDomainAsyncJob asyncJob,
-                   virDomainDiskDefPtr disk)
+                   virDomainDiskDefPtr disk,
+                   char **error)
 {
     qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
     int status = diskPriv->blockJobStatus;
 
+    if (error)
+        *error = NULL;
+
     if (status != -1) {
         qemuBlockJobEventProcess(driver, vm, disk, asyncJob,
                                  diskPriv->blockJobType,
                                  diskPriv->blockJobStatus);
         diskPriv->blockJobStatus = -1;
-        VIR_FREE(diskPriv->blockJobError);
+        if (error)
+            VIR_STEAL_PTR(*error, diskPriv->blockJobError);
+        else
+            VIR_FREE(diskPriv->blockJobError);
     }
 
     return status;
@@ -255,6 +263,6 @@ qemuBlockJobSyncEnd(virQEMUDriverPtr driver,
                     virDomainDiskDefPtr disk)
 {
     VIR_DEBUG("disk=%s", disk->dst);
-    qemuBlockJobUpdate(driver, vm, asyncJob, disk);
+    qemuBlockJobUpdate(driver, vm, asyncJob, disk, NULL);
     QEMU_DOMAIN_DISK_PRIVATE(disk)->blockJobSync = false;
 }
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 47aa4c1..e71d691 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -29,7 +29,8 @@
 int qemuBlockJobUpdate(virQEMUDriverPtr driver,
                        virDomainObjPtr vm,
                        qemuDomainAsyncJob asyncJob,
-                       virDomainDiskDefPtr disk);
+                       virDomainDiskDefPtr disk,
+                       char **error);
 void qemuBlockJobEventProcess(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainDiskDefPtr disk,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6255d89..f6fd6ad 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16596,13 +16596,13 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
                                      VIR_DOMAIN_BLOCK_JOB_CANCELED);
         } else {
             qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
-            qemuBlockJobUpdate(driver, vm, QEMU_ASYNC_JOB_NONE, disk);
+            qemuBlockJobUpdate(driver, vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
             while (diskPriv->blockjob) {
                 if (virDomainObjWait(vm) < 0) {
                     ret = -1;
                     goto endjob;
                 }
-                qemuBlockJobUpdate(driver, vm, QEMU_ASYNC_JOB_NONE, disk);
+                qemuBlockJobUpdate(driver, vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
             }
         }
     }
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 272d525..b7ba4c3 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -611,17 +611,25 @@ qemuMigrationDriveMirrorReady(virQEMUDriverPtr driver,
     for (i = 0; i < vm->def->ndisks; i++) {
         virDomainDiskDefPtr disk = vm->def->disks[i];
         qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+        char *error = NULL;
 
         if (!diskPriv->migrating)
             continue;
 
-        status = qemuBlockJobUpdate(driver, vm, asyncJob, disk);
+        status = qemuBlockJobUpdate(driver, vm, asyncJob, disk, &error);
         if (status == VIR_DOMAIN_BLOCK_JOB_FAILED) {
-            virReportError(VIR_ERR_OPERATION_FAILED,
-                           _("migration of disk %s failed"),
-                           disk->dst);
+            if (error) {
+                virReportError(VIR_ERR_OPERATION_FAILED,
+                               _("migration of disk %s failed: %s"),
+                               disk->dst, error);
+                VIR_FREE(error);
+            } else {
+                virReportError(VIR_ERR_OPERATION_FAILED,
+                               _("migration of disk %s failed"), disk->dst);
+            }
             return -1;
         }
+        VIR_FREE(error);
 
         if (disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_READY)
             notReady++;
@@ -663,17 +671,23 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
     for (i = 0; i < vm->def->ndisks; i++) {
         virDomainDiskDefPtr disk = vm->def->disks[i];
         qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+        char *error = NULL;
 
         if (!diskPriv->migrating)
             continue;
 
-        status = qemuBlockJobUpdate(driver, vm, asyncJob, disk);
+        status = qemuBlockJobUpdate(driver, vm, asyncJob, disk, &error);
         switch (status) {
         case VIR_DOMAIN_BLOCK_JOB_FAILED:
             if (check) {
-                virReportError(VIR_ERR_OPERATION_FAILED,
-                               _("migration of disk %s failed"),
-                               disk->dst);
+                if (error) {
+                    virReportError(VIR_ERR_OPERATION_FAILED,
+                                   _("migration of disk %s failed: %s"),
+                                   disk->dst, error);
+                } else {
+                    virReportError(VIR_ERR_OPERATION_FAILED,
+                                   _("migration of disk %s failed"), disk->dst);
+                }
                 failed = true;
             }
             ATTRIBUTE_FALLTHROUGH;
@@ -689,6 +703,8 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
 
         if (status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
             completed++;
+
+        VIR_FREE(error);
     }
 
     /* Updating completed block job drops the lock thus we have to recheck
@@ -736,24 +752,30 @@ qemuMigrationCancelOneDriveMirror(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *diskAlias = NULL;
+    char *error = NULL;
     int ret = -1;
     int status;
     int rv;
 
-    status = qemuBlockJobUpdate(driver, vm, asyncJob, disk);
+    status = qemuBlockJobUpdate(driver, vm, asyncJob, disk, &error);
     switch (status) {
     case VIR_DOMAIN_BLOCK_JOB_FAILED:
     case VIR_DOMAIN_BLOCK_JOB_CANCELED:
         if (failNoJob) {
-            virReportError(VIR_ERR_OPERATION_FAILED,
-                           _("migration of disk %s failed"),
-                           disk->dst);
-            return -1;
+            if (error) {
+                virReportError(VIR_ERR_OPERATION_FAILED,
+                               _("migration of disk %s failed: %s"),
+                               disk->dst, error);
+            } else {
+                virReportError(VIR_ERR_OPERATION_FAILED,
+                               _("migration of disk %s failed"), disk->dst);
+            }
+            goto cleanup;
         }
-        return 1;
-
+    /* fallthrough */
     case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
-        return 1;
+        ret = 1;
+        goto cleanup;
     }
 
     if (!(diskAlias = qemuAliasFromDisk(disk)))
@@ -771,6 +793,7 @@ qemuMigrationCancelOneDriveMirror(virQEMUDriverPtr driver,
 
  cleanup:
     VIR_FREE(diskAlias);
+    VIR_FREE(error);
     return ret;
 }
 
-- 
1.8.3.1




More information about the libvir-list mailing list