aboutsummaryrefslogtreecommitdiff
path: root/migration/vmstate.c
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2023-09-06 16:47:22 -0400
committerJuan Quintela <quintela@redhat.com>2023-10-04 13:19:47 +0200
commit579cedf430582b37f804f6b6ed131554cebb11b5 (patch)
treecb7b75f3c7a566e96060108046be15fe9213b499 /migration/vmstate.c
parent385f510df5f6a7f3998b3ff01deca33b0027ff29 (diff)
migration: Unify and trace vmstate field_exists() checks
For both save/load we actually share the logic on deciding whether a field should exist. Merge the checks into a helper and use it for both save and load. When doing so, add documentations and reformat the code to make it much easier to read. The real benefit here (besides code cleanups) is we add a trace-point for this; this is a known spot where we can easily break migration compatibilities between binaries, and this trace point will be critical for us to identify such issues. For example, this will be handy when debugging things like: https://gitlab.com/qemu-project/qemu/-/issues/932 Reviewed-by: Fabiano Rosas <farosas@suse.de> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com> Message-ID: <20230906204722.514474-1-peterx@redhat.com>
Diffstat (limited to 'migration/vmstate.c')
-rw-r--r--migration/vmstate.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 4cde30bf2d..1cf9e45b85 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -26,6 +26,30 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
+/* Whether this field should exist for either save or load the VM? */
+static bool
+vmstate_field_exists(const VMStateDescription *vmsd, const VMStateField *field,
+ void *opaque, int version_id)
+{
+ bool result;
+
+ if (field->field_exists) {
+ /* If there's the function checker, that's the solo truth */
+ result = field->field_exists(opaque, version_id);
+ trace_vmstate_field_exists(vmsd->name, field->name, field->version_id,
+ version_id, result);
+ } else {
+ /*
+ * Otherwise, we only save/load if field version is same or older.
+ * For example, when loading from an old binary with old version,
+ * we ignore new fields with newer version_ids.
+ */
+ result = field->version_id <= version_id;
+ }
+
+ return result;
+}
+
static int vmstate_n_elems(void *opaque, const VMStateField *field)
{
int n_elems = 1;
@@ -105,10 +129,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
}
while (field->name) {
trace_vmstate_load_state_field(vmsd->name, field->name);
- if ((field->field_exists &&
- field->field_exists(opaque, version_id)) ||
- (!field->field_exists &&
- field->version_id <= version_id)) {
+ if (vmstate_field_exists(vmsd, field, opaque, version_id)) {
void *first_elem = opaque + field->offset;
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
@@ -349,10 +370,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
}
while (field->name) {
- if ((field->field_exists &&
- field->field_exists(opaque, version_id)) ||
- (!field->field_exists &&
- field->version_id <= version_id)) {
+ if (vmstate_field_exists(vmsd, field, opaque, version_id)) {
void *first_elem = opaque + field->offset;
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);