qemu: Consolidate disk blockjob variables into a structure

Struct qemuDomainDiskPrivate was holding multiple variables connected to
a disk block job. Consolidate them into a new struct qemuBlockJobData.

This will also allow simpler extensions to the block job mechanisms.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2018-10-17 08:57:08 +02:00
parent f5eadd1d92
commit 89a877b312
6 changed files with 65 additions and 38 deletions

View File

@ -42,6 +42,17 @@
VIR_LOG_INIT("qemu.qemu_blockjob"); VIR_LOG_INIT("qemu.qemu_blockjob");
void
qemuBlockJobDataFree(qemuBlockJobDataPtr job)
{
if (!job)
return;
VIR_FREE(job->errmsg);
VIR_FREE(job);
}
/** /**
* qemuBlockJobEmitEvents: * qemuBlockJobEmitEvents:
* *
@ -161,7 +172,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
virStorageSourceBackingStoreClear(disk->src); virStorageSourceBackingStoreClear(disk->src);
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true)); ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true));
ignore_value(qemuBlockNodeNamesDetect(driver, vm, asyncJob)); ignore_value(qemuBlockNodeNamesDetect(driver, vm, asyncJob));
diskPriv->blockjob = false; diskPriv->blockjob->started = false;
break; break;
case VIR_DOMAIN_BLOCK_JOB_READY: case VIR_DOMAIN_BLOCK_JOB_READY:
@ -177,7 +188,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
} }
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
diskPriv->blockjob = false; diskPriv->blockjob->started = false;
break; break;
case VIR_DOMAIN_BLOCK_JOB_LAST: case VIR_DOMAIN_BLOCK_JOB_LAST:
@ -214,22 +225,21 @@ qemuBlockJobUpdateDisk(virDomainObjPtr vm,
virDomainDiskDefPtr disk, virDomainDiskDefPtr disk,
char **error) char **error)
{ {
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuBlockJobDataPtr job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
int status = diskPriv->blockJobStatus; int status = job->status;
if (error) if (error)
*error = NULL; *error = NULL;
if (status != -1) { if (status != -1) {
qemuBlockJobEventProcess(priv->driver, vm, disk, asyncJob, qemuBlockJobEventProcess(priv->driver, vm, disk, asyncJob,
diskPriv->blockJobType, job->type, status);
diskPriv->blockJobStatus); job->status = -1;
diskPriv->blockJobStatus = -1;
if (error) if (error)
VIR_STEAL_PTR(*error, diskPriv->blockJobError); VIR_STEAL_PTR(*error, job->errmsg);
else else
VIR_FREE(diskPriv->blockJobError); VIR_FREE(job->errmsg);
} }
return status; return status;
@ -252,11 +262,11 @@ qemuBlockJobUpdateDisk(virDomainObjPtr vm,
void void
qemuBlockJobSyncBeginDisk(virDomainDiskDefPtr disk) qemuBlockJobSyncBeginDisk(virDomainDiskDefPtr disk)
{ {
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuBlockJobDataPtr job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
VIR_DEBUG("disk=%s", disk->dst); VIR_DEBUG("disk=%s", disk->dst);
diskPriv->blockJobSync = true; job->synchronous = true;
diskPriv->blockJobStatus = -1; job->status = -1;
} }
@ -275,5 +285,5 @@ qemuBlockJobSyncEndDisk(virDomainObjPtr vm,
{ {
VIR_DEBUG("disk=%s", disk->dst); VIR_DEBUG("disk=%s", disk->dst);
qemuBlockJobUpdateDisk(vm, asyncJob, disk, NULL); qemuBlockJobUpdateDisk(vm, asyncJob, disk, NULL);
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockJobSync = false; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->synchronous = false;
} }

View File

@ -25,6 +25,21 @@
# include "internal.h" # include "internal.h"
# include "qemu_conf.h" # include "qemu_conf.h"
typedef struct _qemuBlockJobData qemuBlockJobData;
typedef qemuBlockJobData *qemuBlockJobDataPtr;
struct _qemuBlockJobData {
bool started;
int type;
int status;
char *errmsg;
bool synchronous; /* API call is waiting for this job */
};
void
qemuBlockJobDataFree(qemuBlockJobDataPtr job);
int qemuBlockJobUpdateDisk(virDomainObjPtr vm, int qemuBlockJobUpdateDisk(virDomainObjPtr vm,
int asyncJob, int asyncJob,
virDomainDiskDefPtr disk, virDomainDiskDefPtr disk,

View File

@ -1063,6 +1063,11 @@ qemuDomainDiskPrivateNew(void)
if (!(priv = virObjectNew(qemuDomainDiskPrivateClass))) if (!(priv = virObjectNew(qemuDomainDiskPrivateClass)))
return NULL; return NULL;
if (VIR_ALLOC(priv->blockjob) < 0) {
virObjectUnref(priv);
priv = NULL;
}
return (virObjectPtr) priv; return (virObjectPtr) priv;
} }
@ -1071,10 +1076,10 @@ qemuDomainDiskPrivateDispose(void *obj)
{ {
qemuDomainDiskPrivatePtr priv = obj; qemuDomainDiskPrivatePtr priv = obj;
VIR_FREE(priv->blockJobError);
virStorageSourceFree(priv->migrSource); virStorageSourceFree(priv->migrSource);
VIR_FREE(priv->qomName); VIR_FREE(priv->qomName);
VIR_FREE(priv->nodeCopyOnRead); VIR_FREE(priv->nodeCopyOnRead);
qemuBlockJobDataFree(priv->blockjob);
} }
static virClassPtr qemuDomainStorageSourcePrivateClass; static virClassPtr qemuDomainStorageSourcePrivateClass;
@ -9248,7 +9253,8 @@ qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
return true; return true;
} }
if (diskPriv->blockjob) { if (diskPriv->blockjob &&
diskPriv->blockjob->started) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("disk '%s' already in active block job"), _("disk '%s' already in active block job"),
disk->dst); disk->dst);
@ -9277,7 +9283,7 @@ qemuDomainHasBlockjob(virDomainObjPtr vm,
virDomainDiskDefPtr disk = vm->def->disks[i]; virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
if (!copy_only && diskPriv->blockjob) if (!copy_only && diskPriv->blockjob && diskPriv->blockjob->started)
return true; return true;
if (disk->mirror && disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) if (disk->mirror && disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)

View File

@ -30,6 +30,7 @@
# include "snapshot_conf.h" # include "snapshot_conf.h"
# include "qemu_monitor.h" # include "qemu_monitor.h"
# include "qemu_agent.h" # include "qemu_agent.h"
# include "qemu_blockjob.h"
# include "qemu_conf.h" # include "qemu_conf.h"
# include "qemu_capabilities.h" # include "qemu_capabilities.h"
# include "qemu_migration_params.h" # include "qemu_migration_params.h"
@ -389,13 +390,7 @@ struct _qemuDomainDiskPrivate {
/* ideally we want a smarter way to interlock block jobs on single qemu disk /* ideally we want a smarter way to interlock block jobs on single qemu disk
* in the future, but for now we just disallow any concurrent job on a * in the future, but for now we just disallow any concurrent job on a
* single disk */ * single disk */
bool blockjob; qemuBlockJobDataPtr blockjob;
/* for some synchronous block jobs, we need to notify the owner */
int blockJobType; /* type of the block job from the event */
int blockJobStatus; /* status of the finished block job */
char *blockJobError; /* block job completed event error */
bool blockJobSync; /* the block job needs synchronized termination */
bool migrating; /* the disk is being migrated */ bool migrating; /* the disk is being migrated */
virStorageSourcePtr migrSource; /* disk source object used for NBD migration */ virStorageSourcePtr migrSource; /* disk source object used for NBD migration */

View File

@ -4717,7 +4717,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
int status) int status)
{ {
virDomainDiskDefPtr disk; virDomainDiskDefPtr disk;
qemuDomainDiskPrivatePtr diskPriv; qemuBlockJobDataPtr job;
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
return; return;
@ -4732,10 +4732,10 @@ processBlockJobEvent(virQEMUDriverPtr driver,
goto endjob; goto endjob;
} }
diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
diskPriv->blockJobType = type; job->type = type;
diskPriv->blockJobStatus = status; job->status = status;
qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL); qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
@ -17342,7 +17342,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
if (ret < 0) if (ret < 0)
goto endjob; goto endjob;
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true;
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
VIR_WARN("Unable to save status on vm %s after state change", VIR_WARN("Unable to save status on vm %s after state change",
@ -17449,7 +17449,7 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
if (!async) { if (!async) {
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL); qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
while (diskPriv->blockjob) { while (diskPriv->blockjob->started) {
if (virDomainObjWait(vm) < 0) { if (virDomainObjWait(vm) < 0) {
ret = -1; ret = -1;
goto endjob; goto endjob;
@ -17873,7 +17873,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
disk->mirror = mirror; disk->mirror = mirror;
mirror = NULL; mirror = NULL;
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true;
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
VIR_WARN("Unable to save status on vm %s after state change", VIR_WARN("Unable to save status on vm %s after state change",
@ -18273,7 +18273,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
} }
if (ret == 0) { if (ret == 0) {
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true;
mirror = NULL; mirror = NULL;
} else { } else {
disk->mirror = NULL; disk->mirror = NULL;

View File

@ -927,7 +927,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virQEMUDriverPtr driver = opaque; virQEMUDriverPtr driver = opaque;
struct qemuProcessEvent *processEvent = NULL; struct qemuProcessEvent *processEvent = NULL;
virDomainDiskDefPtr disk; virDomainDiskDefPtr disk;
qemuDomainDiskPrivatePtr diskPriv; qemuBlockJobDataPtr job;
char *data = NULL; char *data = NULL;
virObjectLock(vm); virObjectLock(vm);
@ -937,14 +937,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL))) if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL)))
goto error; goto error;
diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
if (diskPriv->blockJobSync) { job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
if (job->synchronous) {
/* We have a SYNC API waiting for this event, dispatch it back */ /* We have a SYNC API waiting for this event, dispatch it back */
diskPriv->blockJobType = type; job->type = type;
diskPriv->blockJobStatus = status; job->status = status;
VIR_FREE(diskPriv->blockJobError); VIR_FREE(job->errmsg);
ignore_value(VIR_STRDUP_QUIET(diskPriv->blockJobError, error)); ignore_value(VIR_STRDUP_QUIET(job->errmsg, error));
virDomainObjBroadcast(vm); virDomainObjBroadcast(vm);
} else { } else {
/* there is no waiting SYNC API, dispatch the update to a thread */ /* there is no waiting SYNC API, dispatch the update to a thread */