Add a field tracking the current state of job so that it can be queried
later. Until now the job state e.g. that the job is _READY for
finalizing was tracked only for mirror jobs. Add tracking of state for
all jobs.
Similarly to 'qemuBlockJobType' this maps the existing states of the
blockjob from virConnectDomainEventBlockJobStatus to
'qemuBlockJobState' so that we can track some internal states as well.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_blockjob.c | 23 +++++++++++++++--------
src/qemu/qemu_blockjob.h | 22 +++++++++++++++++++++-
src/qemu/qemu_domain.c | 5 +++--
src/qemu/qemu_driver.c | 3 +--
src/qemu/qemu_migration.c | 8 ++++++--
src/qemu/qemu_process.c | 4 +++-
6 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 0b2c667dae..e778e5b7ce 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -79,7 +79,6 @@ qemuBlockJobDataNew(void)
static void
qemuBlockJobDataReset(qemuBlockJobDataPtr job)
{
- job->started = false;
job->type = -1;
job->newstate = -1;
VIR_FREE(job->errmsg);
@@ -104,6 +103,7 @@ qemuBlockJobDiskNew(virDomainDiskDefPtr disk,
qemuBlockJobDataReset(job);
+ job->state = QEMU_BLOCKJOB_STATE_NEW;
job->type = type;
return virObjectRef(job);
@@ -137,7 +137,7 @@ qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk)
void
qemuBlockJobStarted(qemuBlockJobDataPtr job)
{
- job->started = true;
+ job->state = QEMU_BLOCKJOB_STATE_RUNNING;
}
@@ -155,13 +155,21 @@ qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job)
if (!job)
return;
- if (!job->started)
+ if (job->state == QEMU_BLOCKJOB_STATE_NEW)
qemuBlockJobDataReset(job);
virObjectUnref(job);
}
+bool
+qemuBlockJobIsRunning(qemuBlockJobDataPtr job)
+{
+ return job->state == QEMU_BLOCKJOB_STATE_RUNNING ||
+ job->state == QEMU_BLOCKJOB_STATE_READY;
+}
+
+
/**
* qemuBlockJobEmitEvents:
*
@@ -195,7 +203,6 @@ qemuBlockJobEventProcessLegacyCompleted(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk,
int asyncJob)
{
- qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
virDomainDiskDefPtr persistDisk = NULL;
if (disk->mirrorState == VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT) {
@@ -249,7 +256,6 @@ qemuBlockJobEventProcessLegacyCompleted(virQEMUDriverPtr driver,
virStorageSourceBackingStoreClear(disk->src);
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true));
ignore_value(qemuBlockNodeNamesDetect(driver, vm, asyncJob));
- diskPriv->blockjob->started = false;
}
@@ -271,12 +277,12 @@ qemuBlockJobEventProcessLegacy(virQEMUDriverPtr driver,
{
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainDiskDefPtr disk = job->disk;
- qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
- VIR_DEBUG("disk=%s, mirrorState=%s, type=%d, newstate=%d",
+ VIR_DEBUG("disk=%s, mirrorState=%s, type=%d, state=%d, newstate=%d",
disk->dst,
NULLSTR(virDomainDiskMirrorStateTypeToString(disk->mirrorState)),
job->type,
+ job->state,
job->newstate);
qemuBlockJobEmitEvents(driver, vm, disk, job->type, job->newstate);
@@ -301,13 +307,14 @@ qemuBlockJobEventProcessLegacy(virQEMUDriverPtr driver,
}
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
- diskPriv->blockjob->started = false;
break;
case VIR_DOMAIN_BLOCK_JOB_LAST:
break;
}
+ job->state = job->newstate;
+
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps)
< 0)
VIR_WARN("Unable to save status on vm %s after block job",
vm->def->name);
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 0c2ce46986..67b9c94b64 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -25,6 +25,22 @@
# include "internal.h"
# include "qemu_conf.h"
+/**
+ * This enum has to map all known block job states from enum virDomainBlockJobType
+ * to the same values. All internal blockjobs can be mapped after and don't
+ * need to have stable values.
+ */
+typedef enum {
+ QEMU_BLOCKJOB_STATE_COMPLETED = VIR_DOMAIN_BLOCK_JOB_COMPLETED,
+ QEMU_BLOCKJOB_STATE_FAILED = VIR_DOMAIN_BLOCK_JOB_FAILED,
+ QEMU_BLOCKJOB_STATE_CANCELLED = VIR_DOMAIN_BLOCK_JOB_CANCELED,
+ QEMU_BLOCKJOB_STATE_READY = VIR_DOMAIN_BLOCK_JOB_READY,
+ QEMU_BLOCKJOB_STATE_NEW = VIR_DOMAIN_BLOCK_JOB_LAST,
+ QEMU_BLOCKJOB_STATE_RUNNING,
+ QEMU_BLOCKJOB_STATE_LAST
+} qemuBlockjobState;
+verify((int)QEMU_BLOCKJOB_STATE_NEW == VIR_DOMAIN_BLOCK_JOB_LAST);
+
/**
* This enum has to map all known block job types from enum virDomainBlockJobType
* to the same values. All internal blockjobs can be mapped after and don't
@@ -49,8 +65,8 @@ struct _qemuBlockJobData {
virDomainDiskDefPtr disk; /* may be NULL, if blockjob does not corrspond to any disk
*/
- bool started;
int type; /* qemuBlockjobType */
+ int state; /* qemuBlockjobState */
char *errmsg;
bool synchronous; /* API call is waiting for this job */
@@ -72,6 +88,10 @@ void
qemuBlockJobStarted(qemuBlockJobDataPtr job)
ATTRIBUTE_NONNULL(1);
+bool
+qemuBlockJobIsRunning(qemuBlockJobDataPtr job)
+ ATTRIBUTE_NONNULL(1);
+
void
qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 9c3ab426bd..01b4c97a91 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -9261,7 +9261,7 @@ qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
}
if (diskPriv->blockjob &&
- diskPriv->blockjob->started) {
+ qemuBlockJobIsRunning(diskPriv->blockjob)) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("disk '%s' already in active block job"),
disk->dst);
@@ -9290,7 +9290,8 @@ qemuDomainHasBlockjob(virDomainObjPtr vm,
virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
- if (!copy_only && diskPriv->blockjob &&
diskPriv->blockjob->started)
+ if (!copy_only && diskPriv->blockjob &&
+ qemuBlockJobIsRunning(diskPriv->blockjob))
return true;
if (disk->mirror && disk->mirrorJob ==
VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5fd92ca0c1..f203f89521 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17397,9 +17397,8 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
* do the waiting while still holding the VM job, to prevent newly
* scheduled block jobs from confusing us. */
if (!async) {
- qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
- while (diskPriv->blockjob->started) {
+ while (qemuBlockJobIsRunning(job)) {
if (virDomainObjWait(vm) < 0) {
ret = -1;
goto endjob;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index b9119c5b89..bde8697ede 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -702,8 +702,10 @@ qemuMigrationSrcNBDCopyCancel(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+ qemuBlockJobDataPtr job;
- if (!diskPriv->blockjob->started)
+ if (!(job = qemuBlockJobDiskGetJob(disk)) ||
+ !qemuBlockJobIsRunning(job))
diskPriv->migrating = false;
if (!diskPriv->migrating)
@@ -720,6 +722,8 @@ qemuMigrationSrcNBDCopyCancel(virQEMUDriverPtr driver,
qemuBlockJobSyncEndDisk(vm, asyncJob, disk);
diskPriv->migrating = false;
}
+
+ virObjectUnref(job);
}
while ((rv = qemuMigrationSrcNBDCopyCancelled(vm, asyncJob, check)) != 1) {
@@ -5396,7 +5400,7 @@ qemuMigrationSrcCancel(virQEMUDriverPtr driver,
qemuBlockJobDataPtr job;
if (!(job = qemuBlockJobDiskGetJob(disk)) ||
- !job->started)
+ !qemuBlockJobIsRunning(job))
diskPriv->migrating = false;
if (diskPriv->migrating) {
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 91c99a2a11..1171da62a8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7783,8 +7783,10 @@ qemuProcessRefreshLegacyBlockjob(void *payload,
if (disk->mirror) {
if (info->ready == 1 ||
- (info->ready == -1 && info->end == info->cur))
+ (info->ready == -1 && info->end == info->cur)) {
disk->mirrorState = VIR_DOMAIN_BLOCK_JOB_READY;
+ job->state = VIR_DOMAIN_BLOCK_JOB_READY;
+ }
}
qemuBlockJobStartupFinalize(job);
--
2.19.2