Blob Blame History Raw
From 399e5a89b2445523cd0628d07f5ada156725569e Mon Sep 17 00:00:00 2001
Message-Id: <399e5a89b2445523cd0628d07f5ada156725569e@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 21 Jul 2015 16:18:35 +0200
Subject: [PATCH] virsh: Refactor block job waiting in cmdBlockCopy

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

Similarly to the refactor of cmdBlockCommit in a previous commit this
does the same change for cmdBlockCopy.

(cherry picked from commit faa143912381aa48e33839b194b32cc14d574589)

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 tools/virsh-domain.c | 119 ++++++++++++++-------------------------------------
 1 file changed, 31 insertions(+), 88 deletions(-)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8c5ef34..a61656f 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -2263,20 +2263,13 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
     bool blocking = vshCommandOptBool(cmd, "wait") || finish || pivot;
     bool async = vshCommandOptBool(cmd, "async");
     int timeout = 0;
-    struct sigaction sig_action;
-    struct sigaction old_sig_action;
-    sigset_t sigmask, oldsigmask;
-    struct timeval start;
-    struct timeval curr;
     const char *path = NULL;
-    bool quit = false;
     int abort_flags = 0;
     const char *xml = NULL;
     char *xmlstr = NULL;
     virTypedParameterPtr params = NULL;
+    vshBlockJobWaitDataPtr bjWait = NULL;
     int nparams = 0;
-    int status = -1;
-    int cb_id = -1;
 
     if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
         return false;
@@ -2335,33 +2328,14 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
         }
     }
 
-    if (blocking) {
-        sigemptyset(&sigmask);
-        sigaddset(&sigmask, SIGINT);
-
-        intCaught = 0;
-        sig_action.sa_sigaction = vshCatchInt;
-        sig_action.sa_flags = SA_SIGINFO;
-        sigemptyset(&sig_action.sa_mask);
-        sigaction(SIGINT, &sig_action, &old_sig_action);
-
-        GETTIMEOFDAY(&start);
-    }
-
-    virConnectDomainEventGenericCallback cb =
-        VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler);
-
-    if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn,
-                                                  dom,
-                                                  VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
-                                                  cb,
-                                                  &status,
-                                                  NULL)) < 0)
-        vshResetLibvirtError();
-
     if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
         goto cleanup;
 
+    if (blocking &&
+        !(bjWait = vshBlockJobWaitInit(ctl, dom, path, _("Block Copy"), verbose,
+                                       timeout, async)))
+        goto cleanup;
+
     if (xml) {
         if (virFileReadAll(xml, VSH_MAX_XML_FILE, &xmlstr) < 0) {
             vshReportError(ctl);
@@ -2436,83 +2410,52 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
         goto cleanup;
     }
 
-    while (blocking) {
-        virDomainBlockJobInfo info;
-        int result;
-
-        pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask);
-        result = virDomainGetBlockJobInfo(dom, path, &info, 0);
-        pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
-
-        if (result < 0) {
-            vshError(ctl, _("failed to query job for disk %s"), path);
+    /* Execution continues here only if --wait or friends were specified */
+    switch (vshBlockJobWait(bjWait)) {
+        case -1:
             goto cleanup;
-        }
 
-        if (result == 0) {
-            vshError(ctl, _("Block Copy unexpectedly failed"));
+        case VIR_DOMAIN_BLOCK_JOB_CANCELED:
+            vshPrint(ctl, "\n%s", _("Copy aborted"));
             goto cleanup;
-        }
+            break;
 
-        if (verbose)
-            vshPrintJobProgress(_("Block Copy"), info.end - info.cur, info.end);
-        if (info.cur == info.end)
+        case VIR_DOMAIN_BLOCK_JOB_FAILED:
+            vshPrint(ctl, "\n%s", _("Copy failed"));
+            goto cleanup;
             break;
 
-        GETTIMEOFDAY(&curr);
-        if (intCaught || (timeout &&
-                          (((int)(curr.tv_sec - start.tv_sec)  * 1000 +
-                            (int)(curr.tv_usec - start.tv_usec) / 1000) >
-                           timeout))) {
-            vshDebug(ctl, VSH_ERR_DEBUG,
-                     intCaught ? "interrupted" : "timeout");
-            intCaught = 0;
-            timeout = 0;
-            status = VIR_DOMAIN_BLOCK_JOB_CANCELED;
-            if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
-                vshError(ctl, _("failed to abort job for disk %s"), path);
-                goto cleanup;
-            }
-            if (abort_flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)
-                break;
-        } else {
-            usleep(500 * 1000);
-        }
+        case VIR_DOMAIN_BLOCK_JOB_READY:
+        case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
+            break;
     }
 
-    if (status == VIR_DOMAIN_BLOCK_JOB_CANCELED)
-        quit = true;
-
-    if (!quit && pivot) {
+    if (pivot) {
         abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
         if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
             vshError(ctl, _("failed to pivot job for disk %s"), path);
             goto cleanup;
         }
-    } else if (finish && !quit &&
-               virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
-        vshError(ctl, _("failed to finish job for disk %s"), path);
-        goto cleanup;
-    }
-    if (quit)
-        vshPrint(ctl, "\n%s", _("Copy aborted"));
-    else if (pivot)
+
         vshPrint(ctl, "\n%s", _("Successfully pivoted"));
-    else if (finish)
+    } else if (finish) {
+        if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
+            vshError(ctl, _("failed to finish job for disk %s"), path);
+            goto cleanup;
+        }
+
         vshPrint(ctl, "\n%s", _("Successfully copied"));
-    else
+    } else {
         vshPrint(ctl, "\n%s", _("Now in mirroring phase"));
+    }
 
     ret = true;
+
  cleanup:
     VIR_FREE(xmlstr);
     virTypedParamsFree(params, nparams);
-    if (dom)
-        virDomainFree(dom);
-    if (blocking)
-        sigaction(SIGINT, &old_sig_action, NULL);
-    if (cb_id >= 0)
-        virConnectDomainEventDeregisterAny(ctl->conn, cb_id);
+    virDomainFree(dom);
+    vshBlockJobWaitFree(bjWait);
     return ret;
 }
 
-- 
2.5.0