diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 3890e4af95ac023597e98f963827589d7b4885a2..ce4717a2d23e2da2bd191e7f046b54e97c08b578 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -79,7 +79,6 @@ qemuBlockJobDataNew(void) static void qemuBlockJobDataReset(qemuBlockJobDataPtr job) { - job->started = false; job->type = -1; job->newstate = -1; VIR_FREE(job->errmsg); @@ -104,6 +103,7 @@ qemuBlockJobDiskNew(virDomainDiskDefPtr disk, qemuBlockJobDataReset(job); + job->state = QEMU_BLOCKJOB_STATE_NEW; job->type = type; return virObjectRef(job); @@ -137,7 +137,7 @@ qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk) void qemuBlockJobStarted(qemuBlockJobDataPtr job) { - job->started = true; + job->state = QEMU_BLOCKJOB_STATE_RUNNING; } @@ -155,13 +155,21 @@ qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job) if (!job) return; - if (!job->started) + if (job->state == QEMU_BLOCKJOB_STATE_NEW) qemuBlockJobDataReset(job); virObjectUnref(job); } +bool +qemuBlockJobIsRunning(qemuBlockJobDataPtr job) +{ + return job->state == QEMU_BLOCKJOB_STATE_RUNNING || + job->state == QEMU_BLOCKJOB_STATE_READY; +} + + /** * qemuBlockJobEmitEvents: * @@ -196,7 +204,6 @@ qemuBlockJobEventProcessLegacyCompleted(virQEMUDriverPtr driver, virDomainDiskDefPtr disk, int asyncJob) { - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); virDomainDiskDefPtr persistDisk = NULL; if (disk->mirrorState == VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT) { @@ -250,7 +257,6 @@ qemuBlockJobEventProcessLegacyCompleted(virQEMUDriverPtr driver, virStorageSourceBackingStoreClear(disk->src); ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true)); ignore_value(qemuBlockNodeNamesDetect(driver, vm, asyncJob)); - diskPriv->blockjob->started = false; } @@ -272,12 +278,12 @@ qemuBlockJobEventProcessLegacy(virQEMUDriverPtr driver, { virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virDomainDiskDefPtr disk = job->disk; - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - VIR_DEBUG("disk=%s, mirrorState=%s, type=%d, newstate=%d", + VIR_DEBUG("disk=%s, mirrorState=%s, type=%d, state=%d, newstate=%d", disk->dst, NULLSTR(virDomainDiskMirrorStateTypeToString(disk->mirrorState)), job->type, + job->state, job->newstate); qemuBlockJobEmitEvents(driver, vm, disk, job->type, job->newstate); @@ -302,13 +308,14 @@ qemuBlockJobEventProcessLegacy(virQEMUDriverPtr driver, } disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; - diskPriv->blockjob->started = false; break; case VIR_DOMAIN_BLOCK_JOB_LAST: break; } + job->state = job->newstate; + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("Unable to save status on vm %s after block job", vm->def->name); diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h index d37a072aabdc3ccd006c39ddbf17f18a878697aa..a6a2f8b7c7f09cba48b759cfe3e3414a0e8d1003 100644 --- a/src/qemu/qemu_blockjob.h +++ b/src/qemu/qemu_blockjob.h @@ -25,6 +25,22 @@ # include "internal.h" # include "qemu_conf.h" +/** + * This enum has to map all known block job states from enum virDomainBlockJobType + * to the same values. All internal blockjobs can be mapped after and don't + * need to have stable values. + */ +typedef enum { + QEMU_BLOCKJOB_STATE_COMPLETED = VIR_DOMAIN_BLOCK_JOB_COMPLETED, + QEMU_BLOCKJOB_STATE_FAILED = VIR_DOMAIN_BLOCK_JOB_FAILED, + QEMU_BLOCKJOB_STATE_CANCELLED = VIR_DOMAIN_BLOCK_JOB_CANCELED, + QEMU_BLOCKJOB_STATE_READY = VIR_DOMAIN_BLOCK_JOB_READY, + QEMU_BLOCKJOB_STATE_NEW = VIR_DOMAIN_BLOCK_JOB_LAST, + QEMU_BLOCKJOB_STATE_RUNNING, + QEMU_BLOCKJOB_STATE_LAST +} qemuBlockjobState; +verify((int)QEMU_BLOCKJOB_STATE_NEW == VIR_DOMAIN_BLOCK_JOB_LAST); + /** * This enum has to map all known block job types from enum virDomainBlockJobType * to the same values. All internal blockjobs can be mapped after and don't @@ -51,6 +67,7 @@ struct _qemuBlockJobData { bool started; int type; /* qemuBlockJobType */ + int state; /* qemuBlockjobState */ char *errmsg; bool synchronous; /* API call is waiting for this job */ @@ -72,6 +89,10 @@ void qemuBlockJobStarted(qemuBlockJobDataPtr job) ATTRIBUTE_NONNULL(1); +bool +qemuBlockJobIsRunning(qemuBlockJobDataPtr job) + ATTRIBUTE_NONNULL(1); + void qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 7030aa448e14fe78991d61bdabe8a39765718c50..9924730b89225a0eddca1365e73a6342a64fe400 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9254,7 +9254,7 @@ qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk) } if (diskPriv->blockjob && - diskPriv->blockjob->started) { + qemuBlockJobIsRunning(diskPriv->blockjob)) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("disk '%s' already in active block job"), disk->dst); @@ -9283,7 +9283,8 @@ qemuDomainHasBlockjob(virDomainObjPtr vm, virDomainDiskDefPtr disk = vm->def->disks[i]; qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - if (!copy_only && diskPriv->blockjob && diskPriv->blockjob->started) + if (!copy_only && diskPriv->blockjob && + qemuBlockJobIsRunning(diskPriv->blockjob)) return true; if (disk->mirror && disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a65f172ba29412b5d61150144ac4c8d7883ca01a..2f78d1144d20e6c0faab9f0d79a1bd7f64d28552 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -17445,9 +17445,8 @@ qemuDomainBlockJobAbort(virDomainPtr dom, * do the waiting while still holding the VM job, to prevent newly * scheduled block jobs from confusing us. */ if (!async) { - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL); - while (diskPriv->blockjob->started) { + while (qemuBlockJobIsRunning(job)) { if (virDomainObjWait(vm) < 0) { ret = -1; goto endjob; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index bf1b6c5b5ade65baa99dd85b5e6a6f468c09a847..6c5e5170a4ee11241cc5dbb2817c05ca23d8b639 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -702,12 +702,16 @@ qemuMigrationSrcNBDCopyCancel(virQEMUDriverPtr driver, for (i = 0; i < vm->def->ndisks; i++) { virDomainDiskDefPtr disk = vm->def->disks[i]; qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + qemuBlockJobDataPtr job; - if (!diskPriv->blockjob->started) + if (!(job = qemuBlockJobDiskGetJob(disk)) || + !qemuBlockJobIsRunning(job)) diskPriv->migrating = false; - if (!diskPriv->migrating) + if (!diskPriv->migrating) { + virObjectUnref(job); continue; + } rv = qemuMigrationSrcNBDCopyCancelOne(driver, vm, disk, check, asyncJob); @@ -720,6 +724,8 @@ qemuMigrationSrcNBDCopyCancel(virQEMUDriverPtr driver, qemuBlockJobSyncEndDisk(vm, asyncJob, disk); diskPriv->migrating = false; } + + virObjectUnref(job); } while ((rv = qemuMigrationSrcNBDCopyCancelled(vm, asyncJob, check)) != 1) { @@ -5395,7 +5401,7 @@ qemuMigrationSrcCancel(virQEMUDriverPtr driver, qemuBlockJobDataPtr job; if (!(job = qemuBlockJobDiskGetJob(disk)) || - !job->started) + !qemuBlockJobIsRunning(job)) diskPriv->migrating = false; if (diskPriv->migrating) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 226d2ba5c8f1afa95fd4ddaab772abdaef136e69..45870399769492ef6d3148916f810c100d7d3da2 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7846,8 +7846,10 @@ qemuProcessRefreshLegacyBlockjob(void *payload, if (disk->mirror) { if (info->ready == 1 || - (info->ready == -1 && info->end == info->cur)) + (info->ready == -1 && info->end == info->cur)) { disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY; + job->state = VIR_DOMAIN_BLOCK_JOB_READY; + } } qemuBlockJobStartupFinalize(job);