qemu: blockjob: Add functions for block job state control

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 <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2018-11-19 16:48:09 +01:00
parent b44f1cd7d7
commit e0c4d4fcf0
5 changed files with 141 additions and 14 deletions

View File

@ -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:
*

View File

@ -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 */

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}