From 2da32ff468ac7936f190ed86fe3a7188a1972782 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Wed, 13 Nov 2024 09:44:03 +0100 Subject: [PATCH] qemu: monitor: Extract vmstate presence for internal snapshots in qemuBlockGetNamedNodeData 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 Reviewed-by: Michal Privoznik --- src/qemu/qemu_monitor.h | 12 ++++++++++-- src/qemu/qemu_monitor_json.c | 18 ++++++++++++++---- src/qemu/qemu_snapshot.c | 6 ++---- tests/qemublocktest.c | 14 +++++++++++--- .../bitmap/snapshots-internal.out | 2 +- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index aded771315..89a59dfd27 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -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; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b3924461a9..1b4288b744 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -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); } } diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 4a17935627..aab06a09c6 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -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); } } diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index ac4d87b527..be3e421ac0 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -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); diff --git a/tests/qemublocktestdata/bitmap/snapshots-internal.out b/tests/qemublocktestdata/bitmap/snapshots-internal.out index f2fb0a1dcc..dbb3cfded4 100644 --- a/tests/qemublocktestdata/bitmap/snapshots-internal.out +++ b/tests/qemublocktestdata/bitmap/snapshots-internal.out @@ -1,2 +1,2 @@ libvirt-1-format: - internal snapshots: '1727868651' '1727872064' + internal snapshots: '1727868651'(*) '1727872064'(*)