New calc_size field in VMStateField is supposed to help us easily add save/restore support of dynamically allocated buffers in device's states. There are some cases when information on size of dynamically allocated buffer is already presented in specific device's state structure, but in such a form, that can not be used with existing VMStateField interface. Currently, we either can get size from another variable in device's state as it is with VMSTATE_VBUFFER_* macros, or we can also multiply value kept in a variable by a constant with VMSTATE_BUFFER_MULTIPLY macro. If we need to perform any other action, we're forced to add additional variable with size information to device state structure with the only intention to use it in VMStateDescription structure. This approach is not very pretty. Adding extra flags to VMStateFlags enum for every other possible operation with size field seems redundant, and still it would't cover cases when we need to perform a set of operations to get size value. With this new .calc_size field we can calculate size of dynamic array in whichever way we need.
Signed-off-by: Mitsyanko Igor <i.mitsya...@samsung.com> --- hw/hw.h | 14 +++++++------- savevm.c | 14 ++++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/hw/hw.h b/hw/hw.h index efa04d1..8ce4475 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -303,9 +303,9 @@ enum VMStateFlags { VMS_ARRAY_OF_POINTER = 0x040, VMS_VARRAY_UINT16 = 0x080, /* Array with size in uint16_t field */ VMS_VBUFFER = 0x100, /* Buffer with size in int32_t field */ - VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */ - VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/ - VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/ + VMS_CALC_SIZE = 0x200, /* calculate size of dynamic buffer */ + VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field */ + VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field */ }; typedef struct { @@ -321,6 +321,7 @@ typedef struct { const VMStateDescription *vmsd; int version_id; bool (*field_exists)(void *opaque, int version_id); + int (*calc_size)(void *opaque, int version_id); } VMStateField; typedef struct VMStateSubsection { @@ -584,14 +585,13 @@ extern const VMStateInfo vmstate_info_unused_buffer; .offset = vmstate_offset_buffer(_state, _field) + _start, \ } -#define VMSTATE_BUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \ +#define VMSTATE_VBUFFER_CALCSIZE(_field, _state, _version, _test, _start, _calc_size) { \ .name = (stringify(_field)), \ .version_id = (_version), \ .field_exists = (_test), \ - .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\ - .size = (_multiply), \ + .calc_size = (_calc_size), \ .info = &vmstate_info_buffer, \ - .flags = VMS_VBUFFER|VMS_MULTIPLY, \ + .flags = VMS_VBUFFER|VMS_CALC_SIZE|VMS_POINTER, \ .offset = offsetof(_state, _field), \ .start = (_start), \ } diff --git a/savevm.c b/savevm.c index f153c25..19f8985 100644 --- a/savevm.c +++ b/savevm.c @@ -1412,9 +1412,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, int size = field->size; if (field->flags & VMS_VBUFFER) { - size = *(int32_t *)(opaque+field->size_offset); - if (field->flags & VMS_MULTIPLY) { - size *= field->size; + if (field->flags & VMS_CALC_SIZE) { + size = field->calc_size(opaque, vmsd->version_id); + } else { + size = *(int32_t *)(opaque+field->size_offset); } } if (field->flags & VMS_ARRAY) { @@ -1476,9 +1477,10 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, int size = field->size; if (field->flags & VMS_VBUFFER) { - size = *(int32_t *)(opaque+field->size_offset); - if (field->flags & VMS_MULTIPLY) { - size *= field->size; + if (field->flags & VMS_CALC_SIZE) { + size = field->calc_size(opaque, vmsd->version_id); + } else { + size = *(int32_t *)(opaque+field->size_offset); } } if (field->flags & VMS_ARRAY) { -- 1.7.4.1