mirror of
https://github.com/qemu/qemu.git
synced 2026-02-10 13:52:07 +00:00
migration: Add error-parameterized function variants in VMSD struct
- We need to have good error reporting in the callbacks in VMStateDescription struct. Specifically pre_save, pre_load and post_load callbacks. - It is not possible to change these functions everywhere in one patch, therefore, we introduce a duplicate set of callbacks with Error object passed to them. - So, in this commit, we implement 'errp' variants of these callbacks, introducing an explicit Error object parameter. - This is a functional step towards transitioning the entire codebase to the new error-parameterized functions. - Deliberately called in mutual exclusion from their counterparts, to prevent conflicts during the transition. - New impls should preferentally use 'errp' variants of these methods, and existing impls incrementally converted. The variants without 'errp' are intended to be removed once all usage is converted. Reviewed-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Arun Menon <armenon@redhat.com> Tested-by: Fabiano Rosas <farosas@suse.de> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Link: https://lore.kernel.org/r/20250918-propagate_tpm_error-v14-26-36f11a6fb9d3@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
This commit is contained in:
@@ -444,6 +444,25 @@ The functions to do that are inside a vmstate definition, and are called:
|
||||
This function is called after we save the state of one device
|
||||
(even upon failure, unless the call to pre_save returned an error).
|
||||
|
||||
Following are the errp variants of these functions.
|
||||
|
||||
- ``int (*pre_load_errp)(void *opaque, Error **errp);``
|
||||
|
||||
This function is called before we load the state of one device.
|
||||
|
||||
- ``int (*post_load_errp)(void *opaque, int version_id, Error **errp);``
|
||||
|
||||
This function is called after we load the state of one device.
|
||||
|
||||
- ``int (*pre_save_errp)(void *opaque, Error **errp);``
|
||||
|
||||
This function is called before we save the state of one device.
|
||||
|
||||
New impls should preferentally use 'errp' variants of these
|
||||
methods and existing impls incrementally converted.
|
||||
The variants without 'errp' are intended to be removed
|
||||
once all usage is converted.
|
||||
|
||||
Example: You can look at hpet.c, that uses the first three functions
|
||||
to massage the state that is transferred.
|
||||
|
||||
|
||||
@@ -200,14 +200,28 @@ struct VMStateDescription {
|
||||
* exclusive. For this reason, also early_setup VMSDs are migrated in a
|
||||
* QEMU_VM_SECTION_FULL section, while save_setup() data is migrated in
|
||||
* a QEMU_VM_SECTION_START section.
|
||||
*
|
||||
* There are duplicate impls of the post/pre save/load hooks.
|
||||
* New impls should preferentally use 'errp' variants of these
|
||||
* methods and existing impls incrementally converted.
|
||||
* The variants without 'errp' are intended to be removed
|
||||
* once all usage is converted.
|
||||
*
|
||||
* For the errp variants,
|
||||
* Returns: 0 on success,
|
||||
* <0 on error where -value is an error number from errno.h
|
||||
*/
|
||||
|
||||
bool early_setup;
|
||||
int version_id;
|
||||
int minimum_version_id;
|
||||
MigrationPriority priority;
|
||||
int (*pre_load)(void *opaque);
|
||||
int (*pre_load_errp)(void *opaque, Error **errp);
|
||||
int (*post_load)(void *opaque, int version_id);
|
||||
int (*post_load_errp)(void *opaque, int version_id, Error **errp);
|
||||
int (*pre_save)(void *opaque);
|
||||
int (*pre_save_errp)(void *opaque, Error **errp);
|
||||
int (*post_save)(void *opaque);
|
||||
bool (*needed)(void *opaque);
|
||||
bool (*dev_unplug_pending)(void *opaque);
|
||||
|
||||
@@ -134,6 +134,7 @@ static void vmstate_handle_alloc(void *ptr, const VMStateField *field,
|
||||
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
void *opaque, int version_id, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
const VMStateField *field = vmsd->fields;
|
||||
int ret = 0;
|
||||
|
||||
@@ -152,7 +153,16 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
trace_vmstate_load_state_end(vmsd->name, "too old", -EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (vmsd->pre_load) {
|
||||
if (vmsd->pre_load_errp) {
|
||||
ret = vmsd->pre_load_errp(opaque, errp);
|
||||
if (ret < 0) {
|
||||
error_prepend(errp, "pre load hook failed for: '%s', "
|
||||
"version_id: %d, minimum version_id: %d, "
|
||||
"ret: %d: ", vmsd->name, vmsd->version_id,
|
||||
vmsd->minimum_version_id, ret);
|
||||
return ret;
|
||||
}
|
||||
} else if (vmsd->pre_load) {
|
||||
ret = vmsd->pre_load(opaque);
|
||||
if (ret) {
|
||||
error_setg(errp, "pre load hook failed for: '%s', "
|
||||
@@ -245,7 +255,14 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
qemu_file_set_error(f, ret);
|
||||
return ret;
|
||||
}
|
||||
if (vmsd->post_load) {
|
||||
if (vmsd->post_load_errp) {
|
||||
ret = vmsd->post_load_errp(opaque, version_id, errp);
|
||||
if (ret < 0) {
|
||||
error_prepend(errp, "post load hook failed for: %s, version_id: "
|
||||
"%d, minimum_version: %d, ret: %d: ", vmsd->name,
|
||||
vmsd->version_id, vmsd->minimum_version_id, ret);
|
||||
}
|
||||
} else if (vmsd->post_load) {
|
||||
ret = vmsd->post_load(opaque, version_id);
|
||||
if (ret < 0) {
|
||||
error_setg(errp,
|
||||
@@ -414,12 +431,20 @@ int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
void *opaque, JSONWriter *vmdesc, int version_id, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
int ret = 0;
|
||||
const VMStateField *field = vmsd->fields;
|
||||
|
||||
trace_vmstate_save_state_top(vmsd->name);
|
||||
|
||||
if (vmsd->pre_save) {
|
||||
if (vmsd->pre_save_errp) {
|
||||
ret = vmsd->pre_save_errp(opaque, errp);
|
||||
trace_vmstate_save_state_pre_save_res(vmsd->name, ret);
|
||||
if (ret < 0) {
|
||||
error_prepend(errp, "pre-save for %s failed, ret: %d: ",
|
||||
vmsd->name, ret);
|
||||
}
|
||||
} else if (vmsd->pre_save) {
|
||||
ret = vmsd->pre_save(opaque);
|
||||
trace_vmstate_save_state_pre_save_res(vmsd->name, ret);
|
||||
if (ret) {
|
||||
|
||||
Reference in New Issue
Block a user