From d1a44634acead75bc48fb9b0f68dc1ebf6c764fd Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Thu, 17 Jan 2019 16:34:11 +0100 Subject: [PATCH] qemu: blockjob: Track current state of blockjob MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Ján Tomko --- src/qemu/qemu_blockjob.c | 23 +++++++++++++++-------- src/qemu/qemu_blockjob.h | 21 +++++++++++++++++++++ src/qemu/qemu_domain.c | 5 +++-- src/qemu/qemu_driver.c | 3 +-- src/qemu/qemu_migration.c | 12 +++++++++--- src/qemu/qemu_process.c | 4 +++- 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 3890e4af95..ce4717a2d2 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: * @@ -196,7 +204,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) { @@ -250,7 +257,6 @@ qemuBlockJobEventProcessLegacyCompleted(virQEMUDriverPtr driver, virStorageSourceBackingStoreClear(disk->src); ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true)); ignore_value(qemuBlockNodeNamesDetect(driver, vm, asyncJob)); - diskPriv->blockjob->started = false; } @@ -272,12 +278,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); @@ -302,13 +308,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 d37a072aab..a6a2f8b7c7 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 @@ -51,6 +67,7 @@ struct _qemuBlockJobData { bool started; int type; /* qemuBlockJobType */ + int state; /* qemuBlockjobState */ char *errmsg; bool synchronous; /* API call is waiting for this job */ @@ -72,6 +89,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 7030aa448e..9924730b89 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9254,7 +9254,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); @@ -9283,7 +9283,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 a65f172ba2..2f78d1144d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -17445,9 +17445,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 bf1b6c5b5a..6c5e5170a4 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -702,12 +702,16 @@ 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) + if (!diskPriv->migrating) { + virObjectUnref(job); continue; + } rv = qemuMigrationSrcNBDCopyCancelOne(driver, vm, disk, check, asyncJob); @@ -720,6 +724,8 @@ qemuMigrationSrcNBDCopyCancel(virQEMUDriverPtr driver, qemuBlockJobSyncEndDisk(vm, asyncJob, disk); diskPriv->migrating = false; } + + virObjectUnref(job); } while ((rv = qemuMigrationSrcNBDCopyCancelled(vm, asyncJob, check)) != 1) { @@ -5395,7 +5401,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 226d2ba5c8..4587039976 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7846,8 +7846,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_DISK_MIRROR_STATE_READY; + job->state = VIR_DOMAIN_BLOCK_JOB_READY; + } } qemuBlockJobStartupFinalize(job);