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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list