On Fri, Mar 13, 2026 at 03:12:14PM +0100, Alexander Mikhalitsyn wrote: > From: Alexander Mikhalitsyn <[email protected]> > > Let's introduce vmstate_{load,save}_field() helpers, they will > be used in next patches to support fully-dynamic arrays with NULLs. > > Signed-off-by: Alexander Mikhalitsyn <[email protected]>
Feel free to rebase to Vladimir's series here, Fabiano already queued it: https://lore.kernel.org/all/[email protected]/#t These codes weren't touched that frequent, it's interesting to see such coinsidence happens. :) > --- > include/migration/vmstate.h | 4 ++ > migration/vmstate.c | 84 +++++++++++++++++++++++-------------- > 2 files changed, 56 insertions(+), 32 deletions(-) > > diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h > index 62c2abd0c49..5d7dfe70643 100644 > --- a/include/migration/vmstate.h > +++ b/include/migration/vmstate.h > @@ -1240,8 +1240,12 @@ extern const VMStateInfo vmstate_info_qlist; > .flags = VMS_END, \ > } > > +int vmstate_load_field(QEMUFile *f, void *pv, size_t size, > + const VMStateField *field, Error **errp); > int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, > void *opaque, int version_id, Error **errp); > +int vmstate_save_field(QEMUFile *f, void *pv, size_t size, > + const VMStateField *field, JSONWriter *vmdesc, Error > **errp); > int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, > void *opaque, JSONWriter *vmdesc, Error **errp); > int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, > diff --git a/migration/vmstate.c b/migration/vmstate.c > index 4d28364f7ba..8d192bcaa27 100644 > --- a/migration/vmstate.c > +++ b/migration/vmstate.c > @@ -131,6 +131,32 @@ static void vmstate_handle_alloc(void *ptr, const > VMStateField *field, > } > } > > +int vmstate_load_field(QEMUFile *f, void *pv, size_t size, > + const VMStateField *field, Error **errp) > +{ > + int ret = 0; > + > + if (field->flags & VMS_STRUCT) { > + ret = vmstate_load_state(f, field->vmsd, pv, > + field->vmsd->version_id, > + errp); > + } else if (field->flags & VMS_VSTRUCT) { > + ret = vmstate_load_state(f, field->vmsd, pv, > + field->struct_version_id, > + errp); > + } else { > + ret = field->info->get(f, pv, size, field); > + if (ret < 0) { > + error_setg(errp, > + "Failed to load element of type %s for %s: " > + "%d", field->info->name, > + field->name, ret); > + } > + } > + > + return ret; > +} > + > int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, > void *opaque, int version_id, Error **errp) > { > @@ -203,24 +229,7 @@ int vmstate_load_state(QEMUFile *f, const > VMStateDescription *vmsd, > inner_field = field; > } > > - if (inner_field->flags & VMS_STRUCT) { > - ret = vmstate_load_state(f, inner_field->vmsd, curr_elem, > - inner_field->vmsd->version_id, > - errp); > - } else if (inner_field->flags & VMS_VSTRUCT) { > - ret = vmstate_load_state(f, inner_field->vmsd, curr_elem, > - inner_field->struct_version_id, > - errp); > - } else { > - ret = inner_field->info->get(f, curr_elem, size, > - inner_field); > - if (ret < 0) { > - error_setg(errp, > - "Failed to load element of type %s for > %s: " > - "%d", inner_field->info->name, > - inner_field->name, ret); > - } > - } > + ret = vmstate_load_field(f, curr_elem, size, inner_field, > errp); > > /* If we used a fake temp field.. free it now */ > if (inner_field != field) { > @@ -427,6 +436,29 @@ int vmstate_save_state(QEMUFile *f, const > VMStateDescription *vmsd, > return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, > vmsd->version_id, errp); > } > > +int vmstate_save_field(QEMUFile *f, void *pv, size_t size, > + const VMStateField *field, JSONWriter *vmdesc, Error > **errp) > +{ > + int ret = 0; > + > + if (field->flags & VMS_STRUCT) { > + ret = vmstate_save_state(f, field->vmsd, pv, vmdesc, errp); > + } else if (field->flags & VMS_VSTRUCT) { > + ret = vmstate_save_state_v(f, field->vmsd, pv, vmdesc, > + field->struct_version_id, errp); > + } else { > + ret = field->info->put(f, pv, size, field, vmdesc); > + if (ret < 0) { > + error_setg(errp, > + "Failed to save element of type %s for %s: " > + "%d", field->info->name, > + field->name, ret); > + } > + } > + > + return ret; > +} > + > int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, > void *opaque, JSONWriter *vmdesc, int version_id, > Error **errp) > { > @@ -528,19 +560,7 @@ int vmstate_save_state_v(QEMUFile *f, const > VMStateDescription *vmsd, > vmsd_desc_field_start(vmsd, vmdesc_loop, inner_field, > i, max_elems); > > - if (inner_field->flags & VMS_STRUCT) { > - ret = vmstate_save_state(f, inner_field->vmsd, > - curr_elem, vmdesc_loop, errp); > - } else if (inner_field->flags & VMS_VSTRUCT) { > - ret = vmstate_save_state_v(f, inner_field->vmsd, > - curr_elem, vmdesc_loop, > - > inner_field->struct_version_id, > - errp); > - } else { > - ret = inner_field->info->put(f, curr_elem, size, > - inner_field, vmdesc_loop); > - } > - > + ret = vmstate_save_field(f, curr_elem, size, inner_field, > vmdesc_loop, errp); > written_bytes = qemu_file_transferred(f) - old_offset; > vmsd_desc_field_end(vmsd, vmdesc_loop, inner_field, > written_bytes); > @@ -551,7 +571,7 @@ int vmstate_save_state_v(QEMUFile *f, const > VMStateDescription *vmsd, > } > > if (ret) { > - error_setg(errp, "Save of field %s/%s failed", > + error_prepend(errp, "Save of field %s/%s failed: ", > vmsd->name, field->name); > if (vmsd->post_save) { > vmsd->post_save(opaque); > -- > 2.47.3 > -- Peter Xu
