7a3408
From 8dff17fed328807c986ee100045ff6464e0b70cf Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <8dff17fed328807c986ee100045ff6464e0b70cf@dist-git>
7a3408
From: Peter Krempa <pkrempa@redhat.com>
7a3408
Date: Tue, 21 Jul 2015 16:18:34 +0200
7a3408
Subject: [PATCH] virsh: Refactor block job waiting in cmdBlockCommit
7a3408
7a3408
https://bugzilla.redhat.com/show_bug.cgi?id=1227551
7a3408
https://bugzilla.redhat.com/show_bug.cgi?id=1197592
7a3408
7a3408
Reuse the vshBlockJobWait infrastructure to refactor cmdBlockCommit to
7a3408
use the common code. This additionally fixes a bug when working with
7a3408
new qemus, where when doing an active commit with --pivot the pivoting
7a3408
would fail, since qemu reaches 100% completion but the job doesn't
7a3408
switch to synchronized phase right away.
7a3408
7a3408
(cherry picked from commit 7408403560f7d054da75acaab855a95c51a92e2b)
7a3408
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
---
7a3408
 tools/virsh-domain.c | 133 ++++++++++++++++-----------------------------------
7a3408
 1 file changed, 40 insertions(+), 93 deletions(-)
7a3408
7a3408
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
7a3408
index 385eba2..8c5ef34 100644
7a3408
--- a/tools/virsh-domain.c
7a3408
+++ b/tools/virsh-domain.c
7a3408
@@ -2026,20 +2026,13 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
7a3408
     bool blocking = vshCommandOptBool(cmd, "wait") || pivot || finish;
7a3408
     bool async = vshCommandOptBool(cmd, "async");
7a3408
     int timeout = 0;
7a3408
-    struct sigaction sig_action;
7a3408
-    struct sigaction old_sig_action;
7a3408
-    sigset_t sigmask, oldsigmask;
7a3408
-    struct timeval start;
7a3408
-    struct timeval curr;
7a3408
     const char *path = NULL;
7a3408
     const char *base = NULL;
7a3408
     const char *top = NULL;
7a3408
-    bool quit = false;
7a3408
     int abort_flags = 0;
7a3408
-    int status = -1;
7a3408
-    int cb_id = -1;
7a3408
     unsigned int flags = 0;
7a3408
     unsigned long bandwidth = 0;
7a3408
+    vshBlockJobWaitDataPtr bjWait = NULL;
7a3408
 
7a3408
     VSH_EXCLUSIVE_OPTIONS("pivot", "keep-overlay");
7a3408
 
7a3408
@@ -2090,120 +2083,74 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
7a3408
     if (async)
7a3408
         abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC;
7a3408
 
7a3408
-    if (blocking) {
7a3408
-        sigemptyset(&sigmask);
7a3408
-        sigaddset(&sigmask, SIGINT);
7a3408
-
7a3408
-        intCaught = 0;
7a3408
-        sig_action.sa_sigaction = vshCatchInt;
7a3408
-        sig_action.sa_flags = SA_SIGINFO;
7a3408
-        sigemptyset(&sig_action.sa_mask);
7a3408
-        sigaction(SIGINT, &sig_action, &old_sig_action);
7a3408
-
7a3408
-        GETTIMEOFDAY(&start;;
7a3408
-    }
7a3408
-
7a3408
     if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
7a3408
         return false;
7a3408
 
7a3408
-    virConnectDomainEventGenericCallback cb =
7a3408
-        VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler);
7a3408
-
7a3408
-    if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn,
7a3408
-                                                  dom,
7a3408
-                                                  VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
7a3408
-                                                  cb,
7a3408
-                                                  &status,
7a3408
-                                                  NULL)) < 0)
7a3408
-        vshResetLibvirtError();
7a3408
+    if (blocking &&
7a3408
+        !(bjWait = vshBlockJobWaitInit(ctl, dom, path, _("Block commit"),
7a3408
+                                       verbose, timeout, async)))
7a3408
+        goto cleanup;
7a3408
 
7a3408
     if (virDomainBlockCommit(dom, path, base, top, bandwidth, flags) < 0)
7a3408
         goto cleanup;
7a3408
 
7a3408
     if (!blocking) {
7a3408
-        vshPrint(ctl, "%s", active ?
7a3408
-                 _("Active Block Commit started") :
7a3408
-                 _("Block Commit started"));
7a3408
+        if (active)
7a3408
+            vshPrint(ctl, "%s", _("Active Block Commit started"));
7a3408
+        else
7a3408
+            vshPrint(ctl, "%s", _("Block Commit started"));
7a3408
+
7a3408
         ret = true;
7a3408
         goto cleanup;
7a3408
     }
7a3408
 
7a3408
-    while (blocking) {
7a3408
-        virDomainBlockJobInfo info;
7a3408
-        int result;
7a3408
+    /* Execution continues here only if --wait or friends were specified */
7a3408
+    switch (vshBlockJobWait(bjWait)) {
7a3408
+        case -1:
7a3408
+            goto cleanup;
7a3408
 
7a3408
-        pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask);
7a3408
-        result = virDomainGetBlockJobInfo(dom, path, &info, 0);
7a3408
-        pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
7a3408
+        case VIR_DOMAIN_BLOCK_JOB_CANCELED:
7a3408
+            vshPrint(ctl, "\n%s", _("Commit aborted"));
7a3408
+            goto cleanup;
7a3408
+            break;
7a3408
 
7a3408
-        if (result < 0) {
7a3408
-            vshError(ctl, _("failed to query job for disk %s"), path);
7a3408
+        case VIR_DOMAIN_BLOCK_JOB_FAILED:
7a3408
+            vshPrint(ctl, "\n%s", _("Commit failed"));
7a3408
             goto cleanup;
7a3408
-        }
7a3408
-        if (result == 0)
7a3408
             break;
7a3408
 
7a3408
-        if (verbose)
7a3408
-            vshPrintJobProgress(_("Block Commit"),
7a3408
-                                info.end - info.cur, info.end);
7a3408
-        if (active && info.cur == info.end)
7a3408
+        case VIR_DOMAIN_BLOCK_JOB_READY:
7a3408
+        case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
7a3408
             break;
7a3408
+    }
7a3408
+
7a3408
+    if (active) {
7a3408
+        if (pivot) {
7a3408
+            abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
7a3408
+            if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
7a3408
+                vshError(ctl, _("failed to pivot job for disk %s"), path);
7a3408
+                goto cleanup;
7a3408
+            }
7a3408
 
7a3408
-        GETTIMEOFDAY(&curr);
7a3408
-        if (intCaught || (timeout &&
7a3408
-                          (((int)(curr.tv_sec - start.tv_sec)  * 1000 +
7a3408
-                            (int)(curr.tv_usec - start.tv_usec) / 1000) >
7a3408
-                           timeout))) {
7a3408
-            vshDebug(ctl, VSH_ERR_DEBUG,
7a3408
-                     intCaught ? "interrupted" : "timeout");
7a3408
-            intCaught = 0;
7a3408
-            timeout = 0;
7a3408
-            status = VIR_DOMAIN_BLOCK_JOB_CANCELED;
7a3408
+            vshPrint(ctl, "\n%s", _("Successfully pivoted"));
7a3408
+        } else if (finish) {
7a3408
             if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
7a3408
-                vshError(ctl, _("failed to abort job for disk %s"), path);
7a3408
+                vshError(ctl, _("failed to finish job for disk %s"), path);
7a3408
                 goto cleanup;
7a3408
             }
7a3408
-            if (abort_flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)
7a3408
-                break;
7a3408
+
7a3408
+            vshPrint(ctl, "\n%s", _("Commit complete, overlay image kept"));
7a3408
         } else {
7a3408
-            usleep(500 * 1000);
7a3408
+            vshPrint(ctl, "\n%s", _("Now in synchronized phase"));
7a3408
         }
7a3408
-    }
7a3408
-
7a3408
-    if (status == VIR_DOMAIN_BLOCK_JOB_CANCELED)
7a3408
-        quit = true;
7a3408
-
7a3408
-    if (verbose && !quit) {
7a3408
-        /* printf [100 %] */
7a3408
-        vshPrintJobProgress(_("Block Commit"), 0, 1);
7a3408
-    }
7a3408
-    if (!quit && pivot) {
7a3408
-        abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
7a3408
-        if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
7a3408
-            vshError(ctl, _("failed to pivot job for disk %s"), path);
7a3408
-            goto cleanup;
7a3408
-        }
7a3408
-    } else if (finish && !quit &&
7a3408
-               virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
7a3408
-        vshError(ctl, _("failed to finish job for disk %s"), path);
7a3408
-        goto cleanup;
7a3408
-    }
7a3408
-    if (quit)
7a3408
-        vshPrint(ctl, "\n%s", _("Commit aborted"));
7a3408
-    else if (pivot)
7a3408
-        vshPrint(ctl, "\n%s", _("Successfully pivoted"));
7a3408
-    else if (!finish && active)
7a3408
-        vshPrint(ctl, "\n%s", _("Now in synchronized phase"));
7a3408
-    else
7a3408
+    } else {
7a3408
         vshPrint(ctl, "\n%s", _("Commit complete"));
7a3408
+    }
7a3408
 
7a3408
     ret = true;
7a3408
  cleanup:
7a3408
     virDomainFree(dom);
7a3408
-    if (blocking)
7a3408
-        sigaction(SIGINT, &old_sig_action, NULL);
7a3408
-    if (cb_id >= 0)
7a3408
-        virConnectDomainEventDeregisterAny(ctl->conn, cb_id);
7a3408
+    vshBlockJobWaitFree(bjWait);
7a3408
     return ret;
7a3408
 }
7a3408
 
7a3408
-- 
7a3408
2.5.0
7a3408