]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: blockjob: Track current state of blockjob
authorPeter Krempa <pkrempa@redhat.com>
Thu, 17 Jan 2019 15:34:11 +0000 (16:34 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 17 Jan 2019 16:12:50 +0000 (17:12 +0100)
Add a field tracking the current state of job so that it can be queried
later. Until now the job state e.g. that the job is _READY for
finalizing was tracked only for mirror jobs. Add tracking of state for
all jobs.

Similarly to 'qemuBlockJobType' this maps the existing states of the
blockjob from virConnectDomainEventBlockJobStatus to
'qemuBlockJobState' so that we can track some internal states as well.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_blockjob.c
src/qemu/qemu_blockjob.h
src/qemu/qemu_domain.c
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/qemu/qemu_process.c

index 3890e4af95ac023597e98f963827589d7b4885a2..ce4717a2d23e2da2bd191e7f046b54e97c08b578 100644 (file)
@@ -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);
 
index d37a072aabdc3ccd006c39ddbf17f18a878697aa..a6a2f8b7c7f09cba48b759cfe3e3414a0e8d1003 100644 (file)
 # 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);
 
index 7030aa448e14fe78991d61bdabe8a39765718c50..9924730b89225a0eddca1365e73a6342a64fe400 100644 (file)
@@ -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)
index a65f172ba29412b5d61150144ac4c8d7883ca01a..2f78d1144d20e6c0faab9f0d79a1bd7f64d28552 100644 (file)
@@ -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;
index bf1b6c5b5ade65baa99dd85b5e6a6f468c09a847..6c5e5170a4ee11241cc5dbb2817c05ca23d8b639 100644 (file)
@@ -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) {
index 226d2ba5c8f1afa95fd4ddaab772abdaef136e69..45870399769492ef6d3148916f810c100d7d3da2 100644 (file)
@@ -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);