Reuse the vshBlockJobWait infrastructure to refactor cmdBlockCommit to
use the common code. This additionally fixes a bug when working with
new qemus, where when doing an active commit with --pivot the pivoting
would fail, since qemu reaches 100% completion but the job doesn't
switch to synchronized phase right away.
---
tools/virsh-domain.c | 131 +++++++++++++++------------------------------------
1 file changed, 39 insertions(+), 92 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index f1006c2..0891813 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -2025,19 +2025,12 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
bool active = vshCommandOptBool(cmd, "active") || pivot || finish;
bool blocking = vshCommandOptBool(cmd, "wait") || pivot || finish;
bool async = vshCommandOptBool(cmd, "async");
+ vshBlockJobWaitDataPtr bjWait = NULL;
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;
const char *base = NULL;
const char *top = NULL;
- bool quit = false;
int abort_flags = 0;
- int status = -1;
- int cb_id = -1;
unsigned int flags = 0;
unsigned long bandwidth = 0;
@@ -2092,120 +2085,74 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
if (async)
abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC;
- 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);
- }
-
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return false;
- 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 (blocking &&
+ !(bjWait = vshBlockJobWaitInit(ctl, dom, path, _("Block commit"),
+ verbose, timeout, async)))
+ goto cleanup;
if (virDomainBlockCommit(dom, path, base, top, bandwidth, flags) < 0)
goto cleanup;
if (!blocking) {
- vshPrint(ctl, "%s", active ?
- _("Active Block Commit started") :
- _("Block Commit started"));
+ if (active)
+ vshPrint(ctl, "%s", _("Active Block Commit started"));
+ else
+ vshPrint(ctl, "%s", _("Block Commit started"));
+
ret = true;
goto cleanup;
}
- while (blocking) {
- virDomainBlockJobInfo info;
- int result;
+ /* Execution continues here only if --wait or friends were specifed */
+ switch (vshBlockJobWait(bjWait)) {
+ case -1:
+ goto cleanup;
- pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask);
- result = virDomainGetBlockJobInfo(dom, path, &info, 0);
- pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
+ case VIR_DOMAIN_BLOCK_JOB_CANCELED:
+ vshPrint(ctl, "\n%s", _("Commit aborted"));
+ goto cleanup;
+ break;
- if (result < 0) {
- vshError(ctl, _("failed to query job for disk %s"), path);
+ case VIR_DOMAIN_BLOCK_JOB_FAILED:
+ vshPrint(ctl, "\n%s", _("Commit failed"));
goto cleanup;
- }
- if (result == 0)
break;
- if (verbose)
- vshPrintJobProgress(_("Block Commit"),
- info.end - info.cur, info.end);
- if (active && info.cur == info.end)
+ case VIR_DOMAIN_BLOCK_JOB_READY:
+ case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
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 (active) {
+ if (pivot) {
+ abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
- vshError(ctl, _("failed to abort job for disk %s"), path);
+ vshError(ctl, _("failed to pivot job for disk %s"), path);
goto cleanup;
}
- if (abort_flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)
- break;
- } else {
- usleep(500 * 1000);
- }
- }
- if (status == VIR_DOMAIN_BLOCK_JOB_CANCELED)
- quit = true;
+ vshPrint(ctl, "\n%s", _("Successfully pivoted"));
+ } else if (finish) {
+ if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
+ vshError(ctl, _("failed to finish job for disk %s"), path);
+ goto cleanup;
+ }
- if (verbose && !quit) {
- /* printf [100 %] */
- vshPrintJobProgress(_("Block Commit"), 0, 1);
- }
- if (!quit && 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;
+ vshPrint(ctl, "\n%s", _("Commit complete, overlay image
kept"));
+ } else {
+ vshPrint(ctl, "\n%s", _("Now in synchronized phase"));
}
- } 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", _("Commit aborted"));
- else if (pivot)
- vshPrint(ctl, "\n%s", _("Successfully pivoted"));
- else if (!finish && active)
- vshPrint(ctl, "\n%s", _("Now in synchronized phase"));
- else
+ } else {
vshPrint(ctl, "\n%s", _("Commit complete"));
+ }
ret = true;
cleanup:
virDomainFree(dom);
- if (blocking)
- sigaction(SIGINT, &old_sig_action, NULL);
- if (cb_id >= 0)
- virConnectDomainEventDeregisterAny(ctl->conn, cb_id);
+ vshBlockJobWaitFree(bjWait);
return ret;
}
--
2.4.5