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 <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Peter Krempa 2024-11-13 09:44:03 +01:00
parent 6902e77c01
commit 2da32ff468
5 changed files with 38 additions and 14 deletions

View File

@ -701,6 +701,13 @@ struct _qemuBlockNamedNodeDataBitmap {
unsigned long long granularity; unsigned long long granularity;
}; };
typedef struct _qemuBlockNamedNodeDataSnapshot qemuBlockNamedNodeDataSnapshot;
struct _qemuBlockNamedNodeDataSnapshot {
bool vmstate;
};
typedef struct _qemuBlockNamedNodeData qemuBlockNamedNodeData; typedef struct _qemuBlockNamedNodeData qemuBlockNamedNodeData;
struct _qemuBlockNamedNodeData { struct _qemuBlockNamedNodeData {
unsigned long long capacity; unsigned long long capacity;
@ -709,8 +716,9 @@ struct _qemuBlockNamedNodeData {
qemuBlockNamedNodeDataBitmap **bitmaps; qemuBlockNamedNodeDataBitmap **bitmaps;
size_t nbitmaps; size_t nbitmaps;
/* NULL terminated string list of internal snapshot names */ /* hash table indexed by snapshot name containing data about snapshots
char **snapshots; * (qemuBlockNamedNodeDataSnapshot) */
GHashTable *snapshots;
/* the cluster size of the image is valid only when > 0 */ /* the cluster size of the image is valid only when > 0 */
unsigned long long clusterSize; unsigned long long clusterSize;

View File

@ -2569,7 +2569,7 @@ qemuMonitorJSONBlockNamedNodeDataFree(qemuBlockNamedNodeData *data)
for (i = 0; i < data->nbitmaps; i++) for (i = 0; i < data->nbitmaps; i++)
qemuMonitorJSONBlockNamedNodeDataBitmapFree(data->bitmaps[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->bitmaps);
g_free(data); g_free(data);
} }
@ -2658,19 +2658,29 @@ qemuMonitorJSONBlockGetNamedNodeDataWorker(size_t pos G_GNUC_UNUSED,
if ((snapshots = virJSONValueObjectGetArray(img, "snapshots"))) { if ((snapshots = virJSONValueObjectGetArray(img, "snapshots"))) {
size_t nsnapshots = virJSONValueArraySize(snapshots); size_t nsnapshots = virJSONValueArraySize(snapshots);
size_t nsnapnames = 0;
size_t i; size_t i;
ent->snapshots = g_new0(char *, nsnapshots + 1); ent->snapshots = virHashNew(g_free);
for (i = 0; i < nsnapshots; i++) { for (i = 0; i < nsnapshots; i++) {
virJSONValue *snapshot = virJSONValueArrayGet(snapshots, i); virJSONValue *snapshot = virJSONValueArrayGet(snapshots, i);
const char *name = virJSONValueObjectGetString(snapshot, "name"); const char *name = virJSONValueObjectGetString(snapshot, "name");
unsigned long long vmstate_size = 0;
qemuBlockNamedNodeDataSnapshot *snd;
if (!name) if (!name)
continue; 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);
} }
} }

View File

@ -3897,8 +3897,7 @@ qemuSnapshotActiveInternalDeleteGetDevices(virDomainObj *vm,
continue; continue;
/* there might be no snapshot for given disk with given name */ /* there might be no snapshot for given disk with given name */
if (!d->snapshots || if (!virHashHasEntry(d->snapshots, snapname))
!g_strv_contains((const char **) d->snapshots, snapname))
continue; continue;
devices[ndevs++] = g_strdup(format_nodename); devices[ndevs++] = g_strdup(format_nodename);
@ -3913,8 +3912,7 @@ qemuSnapshotActiveInternalDeleteGetDevices(virDomainObj *vm,
if ((format_nodename = qemuBlockStorageSourceGetFormatNodename(vm->def->os.loader->nvram)) && if ((format_nodename = qemuBlockStorageSourceGetFormatNodename(vm->def->os.loader->nvram)) &&
(d = virHashLookup(blockNamedNodeData, format_nodename)) && (d = virHashLookup(blockNamedNodeData, format_nodename)) &&
d->snapshots && virHashHasEntry(d->snapshots, snapname)) {
g_strv_contains((const char **) d->snapshots, snapname)) {
devices[ndevs++] = g_strdup(format_nodename); devices[ndevs++] = g_strdup(format_nodename);
} }
} }

View File

@ -598,12 +598,20 @@ testQemuDetectBitmapsWorker(GHashTable *nodedata,
} }
if (data->snapshots) { if (data->snapshots) {
char **sn; g_autofree virHashKeyValuePair *snaps = virHashGetItems(data->snapshots, NULL, true);
virHashKeyValuePair *n;
virBufferAddLit(buf, "internal snapshots:"); virBufferAddLit(buf, "internal snapshots:");
for (sn = data->snapshots; *sn; sn++) for (n = snaps; n->key; n++) {
virBufferAsprintf(buf, " '%s'", *sn); const qemuBlockNamedNodeDataSnapshot *d = n->value;
const char *vms = "";
if (d->vmstate)
vms = "(*)";
virBufferAsprintf(buf, " '%s'%s", (const char *) n->key, vms);
}
} }
virBufferAdjustIndent(buf, -1); virBufferAdjustIndent(buf, -1);

View File

@ -1,2 +1,2 @@
libvirt-1-format: libvirt-1-format:
internal snapshots: '1727868651' '1727872064' internal snapshots: '1727868651'(*) '1727872064'(*)