]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: monitor: Extract vmstate presence for internal snapshots in qemuBlockGetNamedNo...
authorPeter Krempa <pkrempa@redhat.com>
Wed, 13 Nov 2024 08:44:03 +0000 (09:44 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 18 Nov 2024 12:51:13 +0000 (13:51 +0100)
Refactor the parts of qemuBlockGetNamedNodeData which fetch the names of
internal snapshots present in the on-disk state of QCOW2 images to also
extract the presence of the 'vmstate' section.

This requires conversion of the snapshot list to a hash table as we
always know the name of the snapshot that we're looking for, and the
hash table allows also storing of additional data which we'll use to
store the presence of the 'vmstate'.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_snapshot.c
tests/qemublocktest.c
tests/qemublocktestdata/bitmap/snapshots-internal.out

index aded7713155786f60ff895d810f7e5c42d2fc53b..89a59dfd27a0f88ae0a87b97f0ad56659f5cdd13 100644 (file)
@@ -701,6 +701,13 @@ struct _qemuBlockNamedNodeDataBitmap {
     unsigned long long granularity;
 };
 
+
+typedef struct _qemuBlockNamedNodeDataSnapshot qemuBlockNamedNodeDataSnapshot;
+struct _qemuBlockNamedNodeDataSnapshot {
+    bool vmstate;
+};
+
+
 typedef struct _qemuBlockNamedNodeData qemuBlockNamedNodeData;
 struct _qemuBlockNamedNodeData {
     unsigned long long capacity;
@@ -709,8 +716,9 @@ struct _qemuBlockNamedNodeData {
     qemuBlockNamedNodeDataBitmap **bitmaps;
     size_t nbitmaps;
 
-    /* NULL terminated string list of internal snapshot names */
-    char **snapshots;
+    /* hash table indexed by snapshot name containing data about snapshots
+     * (qemuBlockNamedNodeDataSnapshot) */
+    GHashTable *snapshots;
 
     /* the cluster size of the image is valid only when > 0 */
     unsigned long long clusterSize;
index b3924461a903152dd7a628e6b50911a87a5c698c..1b4288b744997b99ba5327ab9651897e78790a26 100644 (file)
@@ -2569,7 +2569,7 @@ qemuMonitorJSONBlockNamedNodeDataFree(qemuBlockNamedNodeData *data)
 
     for (i = 0; i < data->nbitmaps; i++)
         qemuMonitorJSONBlockNamedNodeDataBitmapFree(data->bitmaps[i]);
-    g_strfreev(data->snapshots);
+    g_clear_pointer(&data->snapshots, g_hash_table_unref);
     g_free(data->bitmaps);
     g_free(data);
 }
@@ -2658,19 +2658,29 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
 
     if ((snapshots = virJSONValueObjectGetArray(img, "snapshots"))) {
         size_t nsnapshots = virJSONValueArraySize(snapshots);
-        size_t nsnapnames = 0;
         size_t i;
 
-        ent->snapshots = g_new0(char *, nsnapshots + 1);
+        ent->snapshots = virHashNew(g_free);
 
         for (i = 0; i < nsnapshots; i++) {
             virJSONValue *snapshot = virJSONValueArrayGet(snapshots, i);
             const char *name = virJSONValueObjectGetString(snapshot, "name");
+            unsigned long long vmstate_size = 0;
+            qemuBlockNamedNodeDataSnapshot *snd;
 
             if (!name)
                 continue;
 
-            ent->snapshots[nsnapnames++] = g_strdup(name);
+            ignore_value(virJSONValueObjectGetNumberUlong(snapshot,
+                                                          "vm-state-size",
+                                                          &vmstate_size));
+
+            snd = g_new0(qemuBlockNamedNodeDataSnapshot, 1);
+
+            if (vmstate_size > 0)
+                snd->vmstate = true;
+
+            g_hash_table_insert(ent->snapshots, g_strdup(name), snd);
         }
     }
 
index 4a179356279f533ff4aee9dec8e0d09657d1342a..aab06a09c6d2c5371ae7b7fb4b7ce951162162d3 100644 (file)
@@ -3897,8 +3897,7 @@ qemuSnapshotActiveInternalDeleteGetDevices(virDomainObj *vm,
             continue;
 
         /* there might be no snapshot for given disk  with given name */
-        if (!d->snapshots ||
-            !g_strv_contains((const char **) d->snapshots, snapname))
+        if (!virHashHasEntry(d->snapshots, snapname))
             continue;
 
         devices[ndevs++] = g_strdup(format_nodename);
@@ -3913,8 +3912,7 @@ qemuSnapshotActiveInternalDeleteGetDevices(virDomainObj *vm,
 
         if ((format_nodename = qemuBlockStorageSourceGetFormatNodename(vm->def->os.loader->nvram)) &&
             (d = virHashLookup(blockNamedNodeData, format_nodename)) &&
-            d->snapshots &&
-            g_strv_contains((const char **) d->snapshots, snapname)) {
+            virHashHasEntry(d->snapshots, snapname)) {
             devices[ndevs++] = g_strdup(format_nodename);
         }
     }
index ac4d87b5272cd5352394839ea62feed0f4093f0a..be3e421ac0789465c4438549f597e993b400a67e 100644 (file)
@@ -598,12 +598,20 @@ testQemuDetectBitmapsWorker(GHashTable *nodedata,
     }
 
     if (data->snapshots) {
-        char **sn;
+        g_autofree virHashKeyValuePair *snaps = virHashGetItems(data->snapshots, NULL, true);
+        virHashKeyValuePair *n;
 
         virBufferAddLit(buf, "internal snapshots:");
 
-        for (sn = data->snapshots; *sn; sn++)
-            virBufferAsprintf(buf, " '%s'", *sn);
+        for (n = snaps; n->key; n++) {
+            const qemuBlockNamedNodeDataSnapshot *d = n->value;
+            const char *vms = "";
+
+            if (d->vmstate)
+                vms = "(*)";
+
+            virBufferAsprintf(buf, " '%s'%s", (const char *) n->key, vms);
+        }
     }
 
     virBufferAdjustIndent(buf, -1);
index f2fb0a1dcca7504e8949b7195b44442691736ca3..dbb3cfded4729403bc906b604ddddc0ceaec5378 100644 (file)
@@ -1,2 +1,2 @@
 libvirt-1-format:
- internal snapshots: '1727868651' '1727872064'
+ internal snapshots: '1727868651'(*) '1727872064'(*)