[RFC PATCH 29/41] qemu: blockjob: Introduce 'populate' blockjob

Peter Krempa pkrempa at redhat.com
Tue Jun 9 15:00:36 UTC 2020


This is a helper blockjob which uses the 'block-dirty-bitmap-populate'
command to convert the allocation map of a qcow2 image into a dirty
bitmap.

Internally it's a blockjob so we need to treat it as such. We only care
about the results when there's a sync thread waiting for it, otherwise
we clean up the created bitmap.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_blockjob.c | 69 ++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_blockjob.h | 13 ++++++++
 src/qemu/qemu_domain.c   | 13 ++++++++
 src/qemu/qemu_driver.c   |  1 +
 4 files changed, 96 insertions(+)

diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 17dc08476b..79820c6ca8 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -69,6 +69,7 @@ VIR_ENUM_IMPL(qemuBlockjob,
               "backup",
               "",
               "create",
+              "populate",
               "broken");

 static virClassPtr qemuBlockJobDataClass;
@@ -356,6 +357,38 @@ qemuBlockJobNewCreate(virDomainObjPtr vm,
 }


+/**
+ * qemuBlockJobNewPopulate:
+ * @vm: domain object
+ * @src: storage source the populate job is running on
+ *
+ * Instantiate block job data for running a 'dirty-bitmap-populate' blockjob.
+ * Note that this job is expected to run as part of a single 'modify' qemu
+ * domain job as this job is not registered with the disk itself and @src must
+ * be valid for the whole time the job is running.
+ */
+qemuBlockJobDataPtr
+qemuBlockJobNewPopulate(virDomainObjPtr vm,
+                       virStorageSourcePtr src)
+{
+    g_autoptr(qemuBlockJobData) job = NULL;
+    g_autofree char *jobname = NULL;
+    const char *nodename = src->nodeformat;
+
+    jobname = g_strdup_printf("bitmap-populate-%s", nodename);
+
+    if (!(job = qemuBlockJobDataNew(QEMU_BLOCKJOB_TYPE_POPULATE, jobname)))
+        return NULL;
+
+     job->data.populate.src = src;
+
+    if (qemuBlockJobRegister(job, vm, NULL, true) < 0)
+        return NULL;
+
+    return g_steal_pointer(&job);
+}
+
+
 qemuBlockJobDataPtr
 qemuBlockJobDiskNewCopy(virDomainObjPtr vm,
                         virDomainDiskDefPtr disk,
@@ -1478,6 +1511,38 @@ qemuBlockJobProcessEventConcludedBackup(virQEMUDriverPtr driver,
 }


+static void
+qemuBlockJobProcessEventConcludedPopulate(virQEMUDriverPtr driver,
+                                          virDomainObjPtr vm,
+                                          qemuBlockJobDataPtr job,
+                                          qemuDomainAsyncJob asyncJob)
+{
+    g_autoptr(virJSONValue) actions = NULL;
+
+    /* On successful completion there must be a synchronous handler waiting for
+     * this job. If there isn't one we need to clean up the associated bitmap.
+     */
+    if (job->newstate == QEMU_BLOCKJOB_STATE_COMPLETED &&
+        job->synchronous)
+        return;
+
+    if (qemuMonitorTransactionBitmapRemove(actions,
+                                           job->data.populate.src->nodeformat,
+                                           "libvirt-tmp-bitmap") < 0)
+        return;
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        return;
+
+    qemuMonitorTransaction(qemuDomainGetMonitor(vm), &actions);
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        return;
+
+    return;
+}
+
+
 static void
 qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job,
                                             virQEMUDriverPtr driver,
@@ -1527,6 +1592,10 @@ qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job,
                                                 progressTotal);
         break;

+    case QEMU_BLOCKJOB_TYPE_POPULATE:
+        qemuBlockJobProcessEventConcludedPopulate(driver, vm, job, asyncJob);
+        break;
+
     case QEMU_BLOCKJOB_TYPE_BROKEN:
     case QEMU_BLOCKJOB_TYPE_NONE:
     case QEMU_BLOCKJOB_TYPE_INTERNAL:
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 19498b5bd8..0b9da7dd5b 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -64,6 +64,7 @@ typedef enum {
     /* Additional enum values local to qemu */
     QEMU_BLOCKJOB_TYPE_INTERNAL,
     QEMU_BLOCKJOB_TYPE_CREATE,
+    QEMU_BLOCKJOB_TYPE_POPULATE,
     QEMU_BLOCKJOB_TYPE_BROKEN,
     QEMU_BLOCKJOB_TYPE_LAST
 } qemuBlockJobType;
@@ -119,6 +120,13 @@ struct _qemuBlockJobBackupData {
 };


+typedef struct _qemuBlockJobBitmapPopulateData qemuBlockJobBitmapPopulateData;
+typedef qemuBlockJobBitmapPopulateData *qemuBlockJobDataBitmapPopulatePtr;
+
+struct _qemuBlockJobBitmapPopulateData {
+    virStorageSourcePtr src;
+};
+
 typedef struct _qemuBlockJobData qemuBlockJobData;
 typedef qemuBlockJobData *qemuBlockJobDataPtr;

@@ -140,6 +148,7 @@ struct _qemuBlockJobData {
         qemuBlockJobCreateData create;
         qemuBlockJobCopyData copy;
         qemuBlockJobBackupData backup;
+        qemuBlockJobBitmapPopulateData populate;
     } data;

     int type; /* qemuBlockJobType */
@@ -197,6 +206,10 @@ qemuBlockJobNewCreate(virDomainObjPtr vm,
                       virStorageSourcePtr chain,
                       bool storage);

+qemuBlockJobDataPtr
+qemuBlockJobNewPopulate(virDomainObjPtr vm,
+                        virStorageSourcePtr src);
+
 qemuBlockJobDataPtr
 qemuBlockJobDiskNewCopy(virDomainObjPtr vm,
                         virDomainDiskDefPtr disk,
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 0cd9cf8582..80d1d14e4f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2737,6 +2737,12 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void *payload,
             }
             break;

+        case QEMU_BLOCKJOB_TYPE_POPULATE:
+            if (job->data.populate.src)
+                virBufferAsprintf(&childBuf, "<src node='%s'/>\n", job->data.populate.src->nodeformat);
+
+            break;
+
         case QEMU_BLOCKJOB_TYPE_BROKEN:
         case QEMU_BLOCKJOB_TYPE_NONE:
         case QEMU_BLOCKJOB_TYPE_INTERNAL:
@@ -3364,6 +3370,13 @@ qemuDomainObjPrivateXMLParseBlockjobDataSpecific(qemuBlockJobDataPtr job,
                 goto broken;
             break;

+        case QEMU_BLOCKJOB_TYPE_POPULATE:
+            qemuDomainObjPrivateXMLParseBlockjobNodename(job,
+                                                         "string(./src/@node)",
+                                                         &job->data.populate.src,
+                                                         ctxt);
+            break;
+
         case QEMU_BLOCKJOB_TYPE_BROKEN:
         case QEMU_BLOCKJOB_TYPE_NONE:
         case QEMU_BLOCKJOB_TYPE_INTERNAL:
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5a3b3bb35b..febe417faf 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17263,6 +17263,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
     case QEMU_BLOCKJOB_TYPE_BACKUP:
     case QEMU_BLOCKJOB_TYPE_INTERNAL:
     case QEMU_BLOCKJOB_TYPE_CREATE:
+    case QEMU_BLOCKJOB_TYPE_POPULATE:
     case QEMU_BLOCKJOB_TYPE_BROKEN:
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("job type '%s' does not support pivot"),
-- 
2.26.2




More information about the libvir-list mailing list