From e0c4d4fcf005edb43d3390dba1f055be09a3fde5 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 19 Nov 2018 16:48:09 +0100 Subject: [PATCH] qemu: blockjob: Add functions for block job state control MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Rather than directly modifying fields in the qemuBlockJobDataPtr structure add a bunch of fields which allow to do the transitions. This will help later when adding more complexity to the job handling. APIs introduced in this patch are: qemuBlockJobDiskNew - prepare for starting a new blockjob on a disk qemuBlockJobDiskGetJob - get the block job data structure for a disk For individual job state manipulation the following APIs are added: qemuBlockJobStarted - Sets the job as started with qemu. Until that the job can be cancelled without asking qemu. qemuBlockJobStartupFinalize - finalize job startup. If the job was started in qemu already, just releases reference to the job object. Otherwise clears everything as if the job was never started. Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko --- src/qemu/qemu_blockjob.c | 81 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_blockjob.h | 19 +++++++++ src/qemu/qemu_driver.c | 31 ++++++++++++--- src/qemu/qemu_migration.c | 7 +++- src/qemu/qemu_process.c | 17 ++++---- 5 files changed, 141 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 5c9f263450..085e64a49d 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -76,6 +76,87 @@ qemuBlockJobDataNew(void) } +static void +qemuBlockJobDataReset(qemuBlockJobDataPtr job) +{ + job->started = false; + job->type = -1; + job->newstate = -1; + VIR_FREE(job->errmsg); + job->synchronous = false; +} + + +/** + * qemuBlockJobDiskNew: + * @disk: disk definition + * + * Start/associate a new blockjob with @disk. + * + * Returns 0 on success and -1 on failure. + */ +qemuBlockJobDataPtr +qemuBlockJobDiskNew(virDomainDiskDefPtr disk) +{ + qemuBlockJobDataPtr job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob; + + qemuBlockJobDataReset(job); + return virObjectRef(job); +} + + +/** + * qemuBlockJobDiskGetJob: + * @disk: disk definition + * + * Get a reference to the block job data object associated with @disk. + */ +qemuBlockJobDataPtr +qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk) +{ + qemuBlockJobDataPtr job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob; + + if (!job) + return NULL; + + return virObjectRef(job); +} + + +/** + * qemuBlockJobStarted: + * @job: job data + * + * Mark @job as started in qemu. + */ +void +qemuBlockJobStarted(qemuBlockJobDataPtr job) +{ + job->started = true; +} + + +/** + * qemuBlockJobStartupFinalize: + * @job: job being started + * + * Cancels and clears the job private data if the job was not started with + * qemu (see qemuBlockJobStarted) or just clears up the local reference + * to @job if it was started. + */ +void +qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job) +{ + if (!job) + return; + + if (!job->started) + qemuBlockJobDataReset(job); + + virObjectUnref(job); +} + + /** * qemuBlockJobEmitEvents: * diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h index 9fda68a205..1a8863440d 100644 --- a/src/qemu/qemu_blockjob.h +++ b/src/qemu/qemu_blockjob.h @@ -42,6 +42,21 @@ struct _qemuBlockJobData { qemuBlockJobDataPtr qemuBlockJobDataNew(void); +qemuBlockJobDataPtr +qemuBlockJobDiskNew(virDomainDiskDefPtr disk) + ATTRIBUTE_NONNULL(1); + +qemuBlockJobDataPtr +qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk) + ATTRIBUTE_NONNULL(1); + +void +qemuBlockJobStarted(qemuBlockJobDataPtr job) + ATTRIBUTE_NONNULL(1); + +void +qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job); + int qemuBlockJobUpdateDisk(virDomainObjPtr vm, int asyncJob, virDomainDiskDefPtr disk, @@ -52,4 +67,8 @@ void qemuBlockJobSyncEndDisk(virDomainObjPtr vm, int asyncJob, virDomainDiskDefPtr disk); +qemuBlockJobDataPtr +qemuBlockJobGetByDisk(virDomainDiskDefPtr disk) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + #endif /* LIBVIRT_QEMU_BLOCKJOB_H */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 926b8c7b89..8ecdd6b6f1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4717,7 +4717,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, int status) { virDomainDiskDefPtr disk; - qemuBlockJobDataPtr job; + qemuBlockJobDataPtr job = NULL; if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) return; @@ -4732,7 +4732,11 @@ processBlockJobEvent(virQEMUDriverPtr driver, goto endjob; } - job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob; + if (!(job = qemuBlockJobDiskGetJob(disk))) { + if (!(job = qemuBlockJobDiskNew(disk))) + goto endjob; + qemuBlockJobStarted(job); + } job->type = type; job->newstate = status; @@ -4740,6 +4744,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL); endjob: + qemuBlockJobStartupFinalize(job); qemuDomainObjEndJob(driver, vm); } @@ -17245,6 +17250,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver, char *basePath = NULL; char *backingPath = NULL; unsigned long long speed = bandwidth; + qemuBlockJobDataPtr job = NULL; int ret = -1; if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) { @@ -17311,6 +17317,9 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver, speed <<= 20; } + if (!(job = qemuBlockJobDiskNew(disk))) + goto endjob; + qemuDomainObjEnterMonitor(driver, vm); if (baseSource) basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src, @@ -17324,7 +17333,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver, if (ret < 0) goto endjob; - QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true; + qemuBlockJobStarted(job); if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("Unable to save status on vm %s after state change", @@ -17334,6 +17343,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver, qemuDomainObjEndJob(driver, vm); cleanup: + qemuBlockJobStartupFinalize(job); virObjectUnref(cfg); VIR_FREE(basePath); VIR_FREE(backingPath); @@ -17711,6 +17721,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, const char *format = NULL; virErrorPtr monitor_error = NULL; bool reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT); + qemuBlockJobDataPtr job = NULL; /* Preliminaries: find the disk we are editing, sanity checks */ virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW | @@ -17834,6 +17845,9 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, goto endjob; } + if (!(job = qemuBlockJobDiskNew(disk))) + goto endjob; + /* Actually start the mirroring */ qemuDomainObjEnterMonitor(driver, vm); /* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified @@ -17850,12 +17864,12 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, } /* Update vm in place to match changes. */ + qemuBlockJobStarted(job); need_unlink = false; virStorageFileDeinit(mirror); disk->mirror = mirror; mirror = NULL; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY; - QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true; if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("Unable to save status on vm %s after state change", @@ -17870,6 +17884,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, virSetError(monitor_error); virFreeError(monitor_error); } + qemuBlockJobStartupFinalize(job); cleanup: VIR_FREE(device); @@ -18080,6 +18095,7 @@ qemuDomainBlockCommit(virDomainPtr dom, char *backingPath = NULL; virStorageSourcePtr mirror = NULL; unsigned long long speed = bandwidth; + qemuBlockJobDataPtr job = NULL; /* XXX Add support for COMMIT_DELETE */ virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW | @@ -18240,6 +18256,10 @@ qemuDomainBlockCommit(virDomainPtr dom, disk->mirror = mirror; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT; } + + if (!(job = qemuBlockJobDiskNew(disk))) + goto endjob; + qemuDomainObjEnterMonitor(driver, vm); basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src, baseSource); @@ -18255,7 +18275,7 @@ qemuDomainBlockCommit(virDomainPtr dom, } if (ret == 0) { - QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true; + qemuBlockJobStarted(job); mirror = NULL; } else { disk->mirror = NULL; @@ -18280,6 +18300,7 @@ qemuDomainBlockCommit(virDomainPtr dom, } } virStorageSourceFree(mirror); + qemuBlockJobStartupFinalize(job); qemuDomainObjEndJob(driver, vm); cleanup: diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 1c44ef0254..87b6d0e1e4 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -902,6 +902,7 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver, unsigned int flags) { qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + qemuBlockJobDataPtr job = NULL; char *diskAlias = NULL; int rc; int ret = -1; @@ -909,6 +910,9 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver, if (!(diskAlias = qemuAliasDiskDriveFromDisk(disk))) goto cleanup; + if (!(job = qemuBlockJobDiskNew(disk))) + goto cleanup; + qemuBlockJobSyncBeginDisk(disk); if (flags & VIR_MIGRATE_TLS) { @@ -931,11 +935,12 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver, } diskPriv->migrating = true; - diskPriv->blockjob->started = true; + qemuBlockJobStarted(job); ret = 0; cleanup: + qemuBlockJobStartupFinalize(job); VIR_FREE(diskAlias); return ret; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d5bdd0d74d..4bc1218fab 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -927,7 +927,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, virQEMUDriverPtr driver = opaque; struct qemuProcessEvent *processEvent = NULL; virDomainDiskDefPtr disk; - qemuBlockJobDataPtr job; + qemuBlockJobDataPtr job = NULL; char *data = NULL; virObjectLock(vm); @@ -938,9 +938,9 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL))) goto cleanup; - job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob; + job = qemuBlockJobDiskGetJob(disk); - if (job->synchronous) { + if (job && job->synchronous) { /* We have a SYNC API waiting for this event, dispatch it back */ job->type = type; job->newstate = status; @@ -969,6 +969,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } cleanup: + qemuBlockJobStartupFinalize(job); qemuProcessEventFree(processEvent); virObjectUnlock(vm); return 0; @@ -7827,7 +7828,6 @@ qemuProcessRefreshLegacyBlockjob(void *payload, virDomainObjPtr vm = opaque; qemuMonitorBlockJobInfoPtr info = payload; virDomainDiskDefPtr disk; - qemuDomainDiskPrivatePtr diskPriv; qemuBlockJobDataPtr job; if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, jobname, jobname))) { @@ -7835,8 +7835,10 @@ qemuProcessRefreshLegacyBlockjob(void *payload, return 0; } - diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - job = diskPriv->blockjob; + if (!(job = qemuBlockJobDiskNew(disk))) + return -1; + + qemuBlockJobStarted(job); if (disk->mirror) { if (info->ready == 1 || @@ -7844,8 +7846,7 @@ qemuProcessRefreshLegacyBlockjob(void *payload, disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY; } - job->started = true; - job->newstate = -1; + qemuBlockJobStartupFinalize(job); return 0; } -- 2.39.5