Rather than direclty 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 handing. 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 <pkrempa@xxxxxxxxxx> --- 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 252f1640b2..a3dc231b32 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 7761eee6ae..3d1b389dec 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 /* __QEMU_BLOCKJOB_H__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 637307806b..9e5171744e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4716,7 +4716,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, int status) { virDomainDiskDefPtr disk; - qemuBlockJobDataPtr job; + qemuBlockJobDataPtr job = NULL; if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) return; @@ -4731,7 +4731,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; @@ -4739,6 +4743,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL); endjob: + qemuBlockJobStartupFinalize(job); qemuDomainObjEndJob(driver, vm); } @@ -17197,6 +17202,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) { @@ -17263,6 +17269,9 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver, speed <<= 20; } + if (!(job = qemuBlockJobDiskNew(disk))) + goto endjob; + qemuDomainObjEnterMonitor(driver, vm); if (baseSource) basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src, @@ -17276,7 +17285,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", @@ -17286,6 +17295,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver, qemuDomainObjEndJob(driver, vm); cleanup: + qemuBlockJobStartupFinalize(job); virObjectUnref(cfg); VIR_FREE(basePath); VIR_FREE(backingPath); @@ -17663,6 +17673,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 | @@ -17786,6 +17797,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 @@ -17802,12 +17816,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", @@ -17822,6 +17836,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, virSetError(monitor_error); virFreeError(monitor_error); } + qemuBlockJobStartupFinalize(job); cleanup: VIR_FREE(device); @@ -18032,6 +18047,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 | @@ -18192,6 +18208,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); @@ -18207,7 +18227,7 @@ qemuDomainBlockCommit(virDomainPtr dom, } if (ret == 0) { - QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true; + qemuBlockJobStarted(job); mirror = NULL; } else { disk->mirror = NULL; @@ -18232,6 +18252,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 9d165e27aa..79ad2efe75 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) { @@ -932,11 +936,12 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver, VIR_FREE(diskAlias); 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 2cead713f6..b1fdbca15e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -926,7 +926,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); @@ -937,9 +937,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; @@ -968,6 +968,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } cleanup: + qemuBlockJobStartupFinalize(job); qemuProcessEventFree(processEvent); virObjectUnlock(vm); return 0; @@ -7764,7 +7765,6 @@ qemuProcessRefreshLegacyBlockjob(void *payload, virDomainObjPtr vm = opaque; qemuMonitorBlockJobInfoPtr info = payload; virDomainDiskDefPtr disk; - qemuDomainDiskPrivatePtr diskPriv; qemuBlockJobDataPtr job; if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, jobname, jobname))) { @@ -7772,8 +7772,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 || @@ -7781,8 +7783,7 @@ qemuProcessRefreshLegacyBlockjob(void *payload, disk->mirrorState = VIR_DOMAIN_BLOCK_JOB_READY; } - job->started = true; - job->newstate = -1; + qemuBlockJobStartupFinalize(job); return 0; } -- 2.19.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list