To better track jobs we couldn't parse let's introduce a new job type
which will clarify semantics internally in few places.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_blockjob.c | 25 ++++++++++++++++++-
src/qemu/qemu_blockjob.h | 3 +++
src/qemu/qemu_domain.c | 13 +++++++++-
src/qemu/qemu_driver.c | 1 +
.../blockjob-blockdev-in.xml | 1 +
5 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 6db3e0ca84..d957e3175e 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -66,7 +66,8 @@ VIR_ENUM_IMPL(qemuBlockjob,
"commit",
"active-commit",
"",
- "create");
+ "create",
+ "broken");
static virClassPtr qemuBlockJobDataClass;
@@ -127,6 +128,23 @@ qemuBlockJobDataNew(qemuBlockJobType type,
}
+/**
+ * qemuBlockJobMarkBroken:
+ * @job: job to mark as broken
+ *
+ * In case when we are unable to parse the block job data from the XML
+ * successfully we'll need to mark the job as broken and then attempt to abort
+ * it. This function marks the job as broken.
+ */
+static void
+qemuBlockJobMarkBroken(qemuBlockJobDataPtr job)
+{
+ qemuBlockJobDataDisposeJobdata(job);
+ job->brokentype = job->type;
+ job->type = QEMU_BLOCKJOB_TYPE_BROKEN;
+}
+
+
/**
* qemuBlockJobRegister:
* @job: job to register
@@ -460,6 +478,9 @@ qemuBlockJobRefreshJobs(virQEMUDriverPtr driver,
* in qemu and just forget about it in libvirt because there's not much
* we coud do besides killing the VM */
if (job->invalidData) {
+
+ qemuBlockJobMarkBroken(job);
+
qemuDomainObjEnterMonitor(driver, vm);
rc = qemuMonitorJobCancel(priv->mon, job->name, true);
@@ -1254,6 +1275,8 @@ qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr
job,
qemuBlockJobProcessEventConcludedCopyAbort(driver, vm, job, asyncJob);
break;
+
+ case QEMU_BLOCKJOB_TYPE_BROKEN:
case QEMU_BLOCKJOB_TYPE_NONE:
case QEMU_BLOCKJOB_TYPE_INTERNAL:
case QEMU_BLOCKJOB_TYPE_LAST:
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index d8da918f2f..fdfe2c57ec 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -63,6 +63,7 @@ typedef enum {
/* Additional enum values local to qemu */
QEMU_BLOCKJOB_TYPE_INTERNAL,
QEMU_BLOCKJOB_TYPE_CREATE,
+ QEMU_BLOCKJOB_TYPE_BROKEN,
QEMU_BLOCKJOB_TYPE_LAST
} qemuBlockJobType;
verify((int)QEMU_BLOCKJOB_TYPE_INTERNAL == VIR_DOMAIN_BLOCK_JOB_TYPE_LAST);
@@ -131,6 +132,8 @@ struct _qemuBlockJobData {
int newstate; /* qemuBlockjobState, subset of events emitted by qemu */
+ int brokentype; /* the previous type of a broken blockjob qemuBlockJobType */
+
bool invalidData; /* the job data (except name) is not valid */
bool reconnected; /* internal field for tracking whether job is live after reconnect
to qemu */
};
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index c233a4ba96..d1596a28ca 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2475,6 +2475,8 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void *payload,
virBufferEscapeString(&attrBuf, " type='%s'",
qemuBlockjobTypeToString(job->type));
virBufferEscapeString(&attrBuf, " state='%s'", state);
virBufferEscapeString(&attrBuf, " newstate='%s'", newstate);
+ if (job->brokentype != QEMU_BLOCKJOB_TYPE_NONE)
+ virBufferEscapeString(&attrBuf, " brokentype='%s'",
qemuBlockjobTypeToString(job->brokentype));
virBufferEscapeString(&childBuf, "<errmsg>%s</errmsg>",
job->errmsg);
if (job->disk) {
@@ -2536,6 +2538,8 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void *payload,
virBufferAddLit(&attrBuf, " shallownew='yes'");
break;
+
+ case QEMU_BLOCKJOB_TYPE_BROKEN:
case QEMU_BLOCKJOB_TYPE_NONE:
case QEMU_BLOCKJOB_TYPE_INTERNAL:
case QEMU_BLOCKJOB_TYPE_LAST:
@@ -3100,6 +3104,8 @@ qemuDomainObjPrivateXMLParseBlockjobDataSpecific(qemuBlockJobDataPtr
job,
}
break;
+
+ case QEMU_BLOCKJOB_TYPE_BROKEN:
case QEMU_BLOCKJOB_TYPE_NONE:
case QEMU_BLOCKJOB_TYPE_INTERNAL:
case QEMU_BLOCKJOB_TYPE_LAST:
@@ -3125,6 +3131,7 @@ qemuDomainObjPrivateXMLParseBlockjobData(virDomainObjPtr vm,
g_autoptr(qemuBlockJobData) job = NULL;
g_autofree char *name = NULL;
g_autofree char *typestr = NULL;
+ g_autofree char *brokentypestr = NULL;
int type;
g_autofree char *statestr = NULL;
int state = QEMU_BLOCKJOB_STATE_FAILED;
@@ -3146,13 +3153,17 @@ qemuDomainObjPrivateXMLParseBlockjobData(virDomainObjPtr vm,
* clean it up */
if (!(typestr = virXPathString("string(./@type)", ctxt)) ||
(type = qemuBlockjobTypeFromString(typestr)) < 0) {
- type = QEMU_BLOCKJOB_TYPE_NONE;
+ type = QEMU_BLOCKJOB_TYPE_BROKEN;
invalidData = true;
}
if (!(job = qemuBlockJobDataNew(type, name)))
return -1;
+ if ((brokentypestr = virXPathString("string(./@brokentype)", ctxt))
&&
+ (job->brokentype = qemuBlockjobTypeFromString(brokentypestr)) < 0)
+ job->brokentype = QEMU_BLOCKJOB_TYPE_NONE;
+
if (!(statestr = virXPathString("string(./@state)", ctxt)) ||
(state = qemuBlockjobStateTypeFromString(statestr)) < 0)
invalidData = true;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 669c12d6ca..fa8a948568 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17418,6 +17418,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
case QEMU_BLOCKJOB_TYPE_COMMIT:
case QEMU_BLOCKJOB_TYPE_INTERNAL:
case QEMU_BLOCKJOB_TYPE_CREATE:
+ case QEMU_BLOCKJOB_TYPE_BROKEN:
virReportError(VIR_ERR_OPERATION_INVALID,
_("job type '%s' does not support pivot"),
qemuBlockjobTypeToString(job->type));
diff --git a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
index 4f6930001e..67ab099bd9 100644
--- a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
+++ b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml
@@ -300,6 +300,7 @@
</source>
</src>
</blockjob>
+ <blockjob name='broken-test' type='broken' state='ready'
brokentype='commit'/>
<blockjob name='test-orphan-job0' type='copy'
state='ready'>
<chains>
<disk type='file' format='qcow2'>
--
2.23.0