[libvirt] [PATCH RFC 51/51] qemu: process: Refresh -blockdev based blockjobs on reconnect to qemu

Peter Krempa pkrempa at redhat.com
Wed Dec 12 17:09:07 UTC 2018


Refresh the state of the jobs and process any events that might have
happened while libvirt was not running.

The job state processing requires some care to figure out if a job
needs to be bumped.t

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_blockjob.c | 57 ++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_blockjob.h |  4 +++
 src/qemu/qemu_process.c  |  7 ++++-
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 6aa8b1df51..8631db7986 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -222,6 +222,63 @@ qemuBlockJobIsRunning(qemuBlockJobDataPtr job)
 }


+int
+qemuBlockJobRefreshJobs(virQEMUDriverPtr driver,
+                        virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorJobInfoPtr *jobinfo = NULL;
+    size_t njobinfo = 0;
+    qemuBlockJobDataPtr job = NULL;
+    qemuBlockjobState newstate;
+    size_t i;
+    int ret = -1;
+    int rc;
+
+    qemuDomainObjEnterMonitor(driver, vm);
+
+    rc = qemuMonitorGetJobInfo(priv->mon, &jobinfo, &njobinfo);
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+        goto cleanup;
+
+    for (i = 0; i < njobinfo; i++) {
+        if (!(job = virHashLookup(priv->blockjobs, jobinfo[i]->id))) {
+            VIR_DEBUG("ignoring untracked job '%s'", jobinfo[i]->id);
+            continue;
+        }
+
+        newstate = qemuBlockjobConvertMonitorStatus(jobinfo[i]->status);
+        if (newstate == QEMU_BLOCKJOB_STATE_LAST)
+            continue;
+
+        if (newstate != job->state) {
+            if ((job->state == QEMU_BLOCKJOB_STATE_FAILED ||
+                 job->state == QEMU_BLOCKJOB_STATE_COMPLETED)) {
+                /* preserve the old state but allow the job to be bumped to
+                 * execute the finishing steps */
+                job->newstate = job->state;
+            } else {
+                job->newstate = newstate;
+            }
+        }
+
+        /* qemuBlockJobUpdate checks whether something is needed */
+        qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
+        job = NULL; /* job may have become invalid here */
+    }
+
+    ret = 0;
+
+ cleanup:
+    for (i = 0; i < njobinfo; i++)
+        qemuMonitorJobInfoFree(jobinfo[i]);
+    VIR_FREE(jobinfo);
+
+    return ret;
+}
+
+
 /**
  * qemuBlockJobEmitEvents:
  *
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 9a2d047d03..6e86c78a9b 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -105,6 +105,10 @@ void
 qemuBlockJobStartupFinalize(virDomainObjPtr vm,
                             qemuBlockJobDataPtr job);

+int
+qemuBlockJobRefreshJobs(virQEMUDriverPtr driver,
+                        virDomainObjPtr vm);
+
 int qemuBlockJobUpdate(virDomainObjPtr vm,
                        qemuBlockJobDataPtr job,
                        int asyncJob);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index fb687a1fd9..75edced15d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7895,7 +7895,12 @@ static int
 qemuProcessRefreshBlockjobs(virQEMUDriverPtr driver,
                             virDomainObjPtr vm)
 {
-    return qemuProcessRefreshLegacyBlockjobs(driver, vm);
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+
+    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV))
+        return qemuBlockJobRefreshJobs(driver, vm);
+    else
+        return qemuProcessRefreshLegacyBlockjobs(driver, vm);
 }


-- 
2.19.2




More information about the libvir-list mailing list