]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: blockjob: Add functions for block job state control
authorPeter Krempa <pkrempa@redhat.com>
Mon, 19 Nov 2018 15:48:09 +0000 (16:48 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 17 Jan 2019 16:12:50 +0000 (17:12 +0100)
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>
src/qemu/qemu_blockjob.c
src/qemu/qemu_blockjob.h
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/qemu/qemu_process.c

index 5c9f263450e200c22babe355005d59d55e6229eb..085e64a49da70c5795769bbf4ad640481e35baaa 100644 (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:
  *
index 9fda68a20593af048d2a46941c47eb1cd4c14e03..1a8863440dbe6414c33e591c9fa71a304f2fe39a 100644 (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 */
index 926b8c7b89656b55d9c868e720cc46fb81d3af23..8ecdd6b6f1a50c4084a1a1096381d0e13f61814a 100644 (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:
index 1c44ef0254617fa5ecd8253e16cd9e7d2d29e5dd..87b6d0e1e4c27e6ccd0623b90be7fea9eba36f7e 100644 (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;
 }
index d5bdd0d74d8cbfcbd9b2aadbee576387ce1d5772..4bc1218fabe837d5eead27bd364f1130dda18d78 100644 (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;
 }