Blame SOURCES/libvirt-qemu-blockjob-Handle-pending-blockjob-state-only-when-we-need-it.patch

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