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(a)redhat.com>
---
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