[libvirt] [PATCH v2 23/25] qemu: blockjob: Implement concluded blockjob handler for backup blockjobs

Peter Krempa pkrempa at redhat.com
Tue Dec 3 17:17:45 UTC 2019


After the individual sub-blockjobs of a backup libvirt job finish we
must detect it and notify the parent job, so that it can be properly
terminated.

Since we update job information to determine success of an blockjob we
can directly report back also statistics of the blockjob.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_blockjob.c | 74 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index d434b8bddd..a6b0af182c 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -27,6 +27,7 @@
 #include "qemu_block.h"
 #include "qemu_domain.h"
 #include "qemu_alias.h"
+#include "qemu_backup.h"

 #include "conf/domain_conf.h"
 #include "conf/domain_event.h"
@@ -1272,11 +1273,71 @@ qemuBlockJobProcessEventConcludedCreate(virQEMUDriverPtr driver,
 }


+static void
+qemuBlockJobProcessEventConcludedBackup(virQEMUDriverPtr driver,
+                                        virDomainObjPtr vm,
+                                        qemuBlockJobDataPtr job,
+                                        qemuDomainAsyncJob asyncJob,
+                                        qemuBlockjobState newstate,
+                                        unsigned long long progressCurrent,
+                                        unsigned long long progressTotal)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    uid_t uid;
+    gid_t gid;
+    g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL;
+    g_autoptr(virJSONValue) actions = NULL;
+
+    qemuBackupNotifyBlockjobEnd(vm, job->disk, newstate, progressCurrent, progressTotal);
+
+    if (job->data.backup.store &&
+        !(backend = qemuBlockStorageSourceDetachPrepare(job->data.backup.store, NULL)))
+        return;
+
+    if (job->data.backup.bitmap) {
+        if (!(actions = virJSONValueNewArray()))
+            return;
+
+        if (qemuMonitorTransactionBitmapRemove(actions,
+                                               job->disk->src->nodeformat,
+                                               job->data.backup.bitmap) < 0)
+            return;
+    }
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        return;
+
+    if (backend)
+        qemuBlockStorageSourceAttachRollback(qemuDomainGetMonitor(vm), backend);
+
+    if (actions)
+        qemuMonitorTransaction(qemuDomainGetMonitor(vm), &actions);
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        return;
+
+    if (job->data.backup.store) {
+        qemuDomainStorageSourceAccessRevoke(driver, vm, job->data.backup.store);
+
+        if (job->data.backup.deleteStore &&
+            job->data.backup.store->type == VIR_STORAGE_TYPE_FILE) {
+            qemuDomainGetImageIds(cfg, vm, job->data.backup.store, NULL, &uid, &gid);
+
+            if (virFileRemove(job->data.backup.store->path, uid, gid) < 0)
+                VIR_WARN("failed to remove scratch file '%s'",
+                         job->data.backup.store->path);
+        }
+    }
+}
+
+
 static void
 qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job,
                                             virQEMUDriverPtr driver,
                                             virDomainObjPtr vm,
-                                            qemuDomainAsyncJob asyncJob)
+                                            qemuDomainAsyncJob asyncJob,
+                                            unsigned long long progressCurrent,
+                                            unsigned long long progressTotal)
 {
     bool success = job->newstate == QEMU_BLOCKJOB_STATE_COMPLETED;

@@ -1310,6 +1371,9 @@ qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job,
         break;

     case QEMU_BLOCKJOB_TYPE_BACKUP:
+        qemuBlockJobProcessEventConcludedBackup(driver, vm, job, asyncJob,
+                                                job->newstate, progressCurrent,
+                                                progressTotal);
         break;

     case QEMU_BLOCKJOB_TYPE_BROKEN:
@@ -1336,6 +1400,8 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job,
     size_t njobinfo = 0;
     size_t i;
     bool refreshed = false;
+    unsigned long long progressCurrent = 0;
+    unsigned long long progressTotal = 0;

     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
         goto cleanup;
@@ -1348,6 +1414,9 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job,
             if (STRNEQ_NULLABLE(job->name, jobinfo[i]->id))
                 continue;

+            progressCurrent = jobinfo[i]->progressCurrent;
+            progressTotal = jobinfo[i]->progressTotal;
+
             job->errmsg = g_strdup(jobinfo[i]->error);

             if (job->errmsg)
@@ -1380,7 +1449,8 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job,

     VIR_DEBUG("handling job '%s' state '%d' newstate '%d'", job->name, job->state, job->newstate);

-    qemuBlockJobEventProcessConcludedTransition(job, driver, vm, asyncJob);
+    qemuBlockJobEventProcessConcludedTransition(job, driver, vm, asyncJob,
+                                                progressCurrent, progressTotal);

     /* unplug the backing chains in case the job inherited them */
     if (!job->disk) {
-- 
2.23.0




More information about the libvir-list mailing list