mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07: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
|
This function is called after we save the state of one device
|
||||||
(even upon failure, unless the call to pre_save returned an error).
|
(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
|
Example: You can look at hpet.c, that uses the first three functions
|
||||||
to massage the state that is transferred.
|
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
|
* exclusive. For this reason, also early_setup VMSDs are migrated in a
|
||||||
* QEMU_VM_SECTION_FULL section, while save_setup() data is migrated in
|
* QEMU_VM_SECTION_FULL section, while save_setup() data is migrated in
|
||||||
* a QEMU_VM_SECTION_START section.
|
* 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;
|
bool early_setup;
|
||||||
int version_id;
|
int version_id;
|
||||||
int minimum_version_id;
|
int minimum_version_id;
|
||||||
MigrationPriority priority;
|
MigrationPriority priority;
|
||||||
int (*pre_load)(void *opaque);
|
int (*pre_load)(void *opaque);
|
||||||
|
int (*pre_load_errp)(void *opaque, Error **errp);
|
||||||
int (*post_load)(void *opaque, int version_id);
|
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)(void *opaque);
|
||||||
|
int (*pre_save_errp)(void *opaque, Error **errp);
|
||||||
int (*post_save)(void *opaque);
|
int (*post_save)(void *opaque);
|
||||||
bool (*needed)(void *opaque);
|
bool (*needed)(void *opaque);
|
||||||
bool (*dev_unplug_pending)(void *opaque);
|
bool (*dev_unplug_pending)(void *opaque);
|
||||||
|
|||||||
+28
-3
@@ -134,6 +134,7 @@ static void vmstate_handle_alloc(void *ptr, const VMStateField *field,
|
|||||||
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||||
void *opaque, int version_id, Error **errp)
|
void *opaque, int version_id, Error **errp)
|
||||||
{
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
const VMStateField *field = vmsd->fields;
|
const VMStateField *field = vmsd->fields;
|
||||||
int ret = 0;
|
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);
|
trace_vmstate_load_state_end(vmsd->name, "too old", -EINVAL);
|
||||||
return -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);
|
ret = vmsd->pre_load(opaque);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_setg(errp, "pre load hook failed for: '%s', "
|
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);
|
qemu_file_set_error(f, ret);
|
||||||
return 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);
|
ret = vmsd->post_load(opaque, version_id);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg(errp,
|
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,
|
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
|
||||||
void *opaque, JSONWriter *vmdesc, int version_id, Error **errp)
|
void *opaque, JSONWriter *vmdesc, int version_id, Error **errp)
|
||||||
{
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const VMStateField *field = vmsd->fields;
|
const VMStateField *field = vmsd->fields;
|
||||||
|
|
||||||
trace_vmstate_save_state_top(vmsd->name);
|
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);
|
ret = vmsd->pre_save(opaque);
|
||||||
trace_vmstate_save_state_pre_save_res(vmsd->name, ret);
|
trace_vmstate_save_state_pre_save_res(vmsd->name, ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|||||||
Reference in New Issue
Block a user