[libvirt] [PATCH 19/25] qemu: process: Refresh -blockdev based blockjobs on reconnect to qemu
Ján Tomko
jtomko at redhat.com
Mon Jul 15 15:42:51 UTC 2019
On Fri, Jul 12, 2019 at 06:06:00PM +0200, Peter Krempa wrote:
>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.
>
>For any invalid job try doing our best to cancel it.
>
>Signed-off-by: Peter Krempa <pkrempa at redhat.com>
>---
> src/qemu/qemu_blockjob.c | 109 +++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_blockjob.h | 5 ++
> src/qemu/qemu_process.c | 7 ++-
> 3 files changed, 120 insertions(+), 1 deletion(-)
>
>diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
>index 8b142f1aba..360fc40e61 100644
>--- a/src/qemu/qemu_blockjob.c
>+++ b/src/qemu/qemu_blockjob.c
>@@ -242,6 +242,115 @@ qemuBlockJobIsRunning(qemuBlockJobDataPtr job)
> }
>
>
>+/* returns 1 for a job we didn't reconnect to */
>+static int
>+qemuBlockJobRefreshJobsFindInactive(const void *payload,
>+ const void *name ATTRIBUTE_UNUSED,
>+ const void *data ATTRIBUTE_UNUSED)
>+{
>+ const qemuBlockJobData *job = payload;
>+
>+ return !job->reconnected;
>+}
>+
>+
>+int
>+qemuBlockJobRefreshJobs(virQEMUDriverPtr driver,
>+ virDomainObjPtr vm)
>+{
>+ qemuDomainObjPrivatePtr priv = vm->privateData;
>+ qemuMonitorJobInfoPtr *jobinfo = NULL;
>+ size_t njobinfo = 0;
>+ qemuBlockJobDataPtr job = NULL;
>+ int 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;
>+ }
>+
>+ /* try cancelling invalid jobs - this works only if the job is not
>+ * concluded. In such case it will fail. We'll leave such job linger
>+ * in qemu and just forget about it in libvirt because there's not much
>+ * we coud do besides killing the VM */
>+ if (job->invalidData) {
>+ qemuDomainObjEnterMonitor(driver, vm);
>+
>+ rc = qemuMonitorJobCancel(priv->mon, job->name, true);
>+ if (rc == -1 && jobinfo[i]->status == QEMU_MONITOR_JOB_STATUS_CONCLUDED)
>+ VIR_WARN("can't cancel job '%s' with invalid data", job->name);
>+
>+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
>+ goto cleanup;
>+
>+ if (rc < 0)
>+ qemuBlockJobUnregister(job, vm);
>+ job = NULL;
The value is unused after this.
>+ continue;
>+ }
>+
>+ if ((newstate = qemuBlockjobConvertMonitorStatus(jobinfo[i]->status)) < 0)
>+ 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 if (newstate == QEMU_BLOCKJOB_STATE_CONCLUDED) {
>+ if (VIR_STRDUP(job->errmsg, jobinfo[i]->error) < 0)
>+ goto cleanup;
>+
>+ if (job->errmsg)
>+ job->newstate = QEMU_BLOCKJOB_STATE_FAILED;
>+ else
>+ job->newstate = QEMU_BLOCKJOB_STATE_COMPLETED;
>+ } else if (newstate == QEMU_BLOCKJOB_STATE_READY) {
>+ /* Apply _READY state only if it was not applied before */
>+ if (job->state == QEMU_BLOCKJOB_STATE_NEW ||
>+ job->state == QEMU_BLOCKJOB_STATE_RUNNING)
>+ job->newstate = newstate;
>+ }
>+ /* don't update the job otherwise */
>+ }
>+
>+ job->reconnected = true;
>+
>+ if (job->newstate != -1)
>+ qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
>+ job = NULL; /* job may have become invalid here */
>+ }
>+
>+ /* remove data for job which qemu didn't report (the algorithm is
>+ * inefficient, but the possibility of such jobs is very low */
>+ while ((job = virHashSearch(priv->blockjobs, qemuBlockJobRefreshJobsFindInactive, NULL, NULL))) {
>+ qemuBlockJobUnregister(job, vm);
>+ job = NULL;
>+ }
>+
>+ ret = 0;
>+
>+ cleanup:
>+ for (i = 0; i < njobinfo; i++)
>+ qemuMonitorJobInfoFree(jobinfo[i]);
>+ VIR_FREE(jobinfo);
>+
>+ return ret;
>+}
>+
>+
> /**
> * qemuBlockJobEmitEvents:
> *
Reviewed-by: Ján Tomko <jtomko at redhat.com>
Jano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190715/6b20f713/attachment-0001.sig>
More information about the libvir-list
mailing list