]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: block: Introduce helper function to ensure that block nodes are active
authorPeter Krempa <pkrempa@redhat.com>
Wed, 23 Jul 2025 15:30:02 +0000 (17:30 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 21 Oct 2025 13:32:39 +0000 (15:32 +0200)
Upcoming changes to snapshot code will break the assumption that block
nodes are always active (if the function is able to acquire a modify
job).

Introduce qemuBlockNodesEnsureActive that checks if the block graph in
qemu contains any inactive nodes and if yes reactivates everything.

The function will be used on code paths such as blockjobs which require
the nodes to be active.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_block.c
src/qemu/qemu_block.h

index 194f8407e3005af6569d6abfd1b2e5dd46cf2ed4..a7062d3e969081b68474686c9c9363d6ea1eeccc 100644 (file)
@@ -4023,3 +4023,55 @@ qemuBlockFinalize(virDomainObj *vm,
 
     return ret;
 }
+
+
+/**
+ * qemuBlockNodesEnsureActive:
+ * @vm: domain object
+ * @asyncJob: asynchronous job ID
+ *
+ * Checks if any block nodes are inactive and reactivates them. This is necessary
+ * to do before any blockjob as the block nodes could have been deactivated
+ * either by an aborted migration (before the VM switched to running mode) or
+ * after a snapshot with 'manual' disks (which deactivates them).
+ *
+ * Block nodes need to be reactivated prior to fetching the data
+ * via 'qemuBlockGetNamedNodeData' as qemu doesn't guarantee that the data
+ * fetched while nodes are inactive is accurate.
+ */
+int
+qemuBlockNodesEnsureActive(virDomainObj *vm,
+                           virDomainAsyncJob asyncJob)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    GHashTableIter htitr;
+    g_autoptr(GHashTable) blockNamedNodeData = NULL;
+    qemuBlockNamedNodeData *node;
+    bool has_inactive = false;
+    int rc = 0;
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SET_ACTIVE))
+        return 0;
+
+    if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob)))
+        return -1;
+
+    g_hash_table_iter_init(&htitr, blockNamedNodeData);
+    while (g_hash_table_iter_next(&htitr, NULL, (void *) &node)) {
+        if (node->inactive) {
+            has_inactive = true;
+            break;
+        }
+    }
+
+    if (!has_inactive)
+        return 0;
+
+    if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
+        return -1;
+
+    rc = qemuMonitorBlockdevSetActive(priv->mon, NULL, true);
+    qemuDomainObjExitMonitor(vm);
+
+    return rc;
+}
index b9e950e4940170286c700395cbe9f8e9cb9ad460..ba7e9bbbdae550c9e0dca213354b86b52d6b1616 100644 (file)
@@ -376,3 +376,7 @@ int
 qemuBlockFinalize(virDomainObj *vm,
                   qemuBlockJobData *job,
                   virDomainAsyncJob asyncJob);
+
+int
+qemuBlockNodesEnsureActive(virDomainObj *vm,
+                           virDomainAsyncJob asyncJob);