735c6b
From 11dd7c99fa96364962f81d4efae0ed220c7a7190 Mon Sep 17 00:00:00 2001
735c6b
Message-Id: <11dd7c99fa96364962f81d4efae0ed220c7a7190@dist-git>
735c6b
From: Peter Krempa <pkrempa@redhat.com>
735c6b
Date: Fri, 10 Feb 2023 17:16:43 +0100
735c6b
Subject: [PATCH] qemu: blockjob: Handle 'pending' blockjob state only when we
735c6b
 need it
735c6b
735c6b
The 'pending' state needs to be handled by the blockjob code only when
735c6b
the snapshot code requests a block-commit without auto-finalization.
735c6b
735c6b
If we always handle it we fail to properly remove the blockjob data for
735c6b
the 'blockdev-create' job as that also transitions trhough 'pending' but
735c6b
we'd never update it once it reaches 'concluded' as the code already
735c6b
thinks that the job has finished and is no longer watching it.
735c6b
735c6b
Introduce a 'processPending' property into block job data and set it
735c6b
only when we know that we need to process 'pending'.
735c6b
735c6b
Fixes: 90d9bc9d74a5157167548b26c00b1a016655e295
735c6b
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2168769
735c6b
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
735c6b
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
735c6b
(cherry picked from commit c433c2434c0459df98ed3355ef615e341acd9009)
735c6b
---
735c6b
 src/qemu/qemu_block.c    |  1 +
735c6b
 src/qemu/qemu_blockjob.c | 19 ++++++++++---------
735c6b
 src/qemu/qemu_blockjob.h |  4 ++++
735c6b
 3 files changed, 15 insertions(+), 9 deletions(-)
735c6b
735c6b
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
735c6b
index c218262691..d8ca50d618 100644
735c6b
--- a/src/qemu/qemu_block.c
735c6b
+++ b/src/qemu/qemu_block.c
735c6b
@@ -3374,6 +3374,7 @@ qemuBlockCommit(virDomainObj *vm,
735c6b
     if (!(job = qemuBlockJobDiskNewCommit(vm, disk, top_parent, topSource,
735c6b
                                           baseSource,
735c6b
                                           flags & VIR_DOMAIN_BLOCK_COMMIT_DELETE,
735c6b
+                                          autofinalize,
735c6b
                                           flags)))
735c6b
         goto cleanup;
735c6b
 
735c6b
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
735c6b
index cb2d05d71d..a20cf1db62 100644
735c6b
--- a/src/qemu/qemu_blockjob.c
735c6b
+++ b/src/qemu/qemu_blockjob.c
735c6b
@@ -274,6 +274,7 @@ qemuBlockJobDiskNewCommit(virDomainObj *vm,
735c6b
                           virStorageSource *top,
735c6b
                           virStorageSource *base,
735c6b
                           bool delete_imgs,
735c6b
+                          virTristateBool autofinalize,
735c6b
                           unsigned int jobflags)
735c6b
 {
735c6b
     g_autoptr(qemuBlockJobData) job = NULL;
735c6b
@@ -290,6 +291,7 @@ qemuBlockJobDiskNewCommit(virDomainObj *vm,
735c6b
     job->data.commit.top = top;
735c6b
     job->data.commit.base = base;
735c6b
     job->data.commit.deleteCommittedImages = delete_imgs;
735c6b
+    job->processPending = autofinalize == VIR_TRISTATE_BOOL_NO;
735c6b
     job->jobflags = jobflags;
735c6b
 
735c6b
     if (qemuBlockJobRegister(job, vm, disk, true) < 0)
735c6b
@@ -532,8 +534,6 @@ qemuBlockJobRefreshJobs(virDomainObj *vm)
735c6b
                 if (job->state == QEMU_BLOCKJOB_STATE_NEW ||
735c6b
                     job->state == QEMU_BLOCKJOB_STATE_RUNNING)
735c6b
                     job->newstate = newstate;
735c6b
-            } else if (newstate == QEMU_BLOCKJOB_STATE_PENDING) {
735c6b
-                job->newstate = newstate;
735c6b
             }
735c6b
             /* don't update the job otherwise */
735c6b
         }
735c6b
@@ -1568,13 +1568,14 @@ qemuBlockJobEventProcess(virQEMUDriver *driver,
735c6b
 
735c6b
     case QEMU_BLOCKJOB_STATE_PENDING:
735c6b
         /* Similarly as for 'ready' state we should handle it only when
735c6b
-         * previous state was 'new' or 'running' as there are other cases
735c6b
-         * when it can be emitted by QEMU. Currently we need this only when
735c6b
-         * deleting non-active external snapshots. */
735c6b
-        if (job->state == QEMU_BLOCKJOB_STATE_NEW ||
735c6b
-            job->state == QEMU_BLOCKJOB_STATE_RUNNING) {
735c6b
-            job->state = job->newstate;
735c6b
-            qemuDomainSaveStatus(vm);
735c6b
+         * previous state was 'new' or 'running' and only if the blockjob code
735c6b
+         * is handling finalization of the job explicitly. */
735c6b
+        if (job->processPending) {
735c6b
+            if (job->state == QEMU_BLOCKJOB_STATE_NEW ||
735c6b
+                job->state == QEMU_BLOCKJOB_STATE_RUNNING) {
735c6b
+                job->state = job->newstate;
735c6b
+                qemuDomainSaveStatus(vm);
735c6b
+            }
735c6b
         }
735c6b
         job->newstate = -1;
735c6b
         break;
735c6b
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
735c6b
index e9b283da20..f1ac43b4c7 100644
735c6b
--- a/src/qemu/qemu_blockjob.h
735c6b
+++ b/src/qemu/qemu_blockjob.h
735c6b
@@ -138,6 +138,9 @@ struct _qemuBlockJobData {
735c6b
 
735c6b
     int brokentype; /* the previous type of a broken blockjob qemuBlockJobType */
735c6b
 
735c6b
+    bool processPending; /* process the 'pending' state of the job, if the job
735c6b
+                            should not be auto-finalized */
735c6b
+
735c6b
     bool invalidData; /* the job data (except name) is not valid */
735c6b
     bool reconnected; /* internal field for tracking whether job is live after reconnect to qemu */
735c6b
 };
735c6b
@@ -175,6 +178,7 @@ qemuBlockJobDiskNewCommit(virDomainObj *vm,
735c6b
                           virStorageSource *top,
735c6b
                           virStorageSource *base,
735c6b
                           bool delete_imgs,
735c6b
+                          virTristateBool autofinalize,
735c6b
                           unsigned int jobflags);
735c6b
 
735c6b
 qemuBlockJobData *
735c6b
-- 
735c6b
2.39.1
735c6b