On 05/30/2014 07:34 PM, Alexey Kardashevskiy wrote: > There are few helpers already to support array migration. However they all > require the destination side to preallocate arrays before migration which > is not always possible due to unknown array size as it might be some > sort of dynamic state. One of the examples is an array of MSIX-enabled > devices in SPAPR PHB - this array may vary from 0 to 65536 entries and > its size depends on guest's ability to enable MSIX or do PCI hotplug. > > This adds new VMSTATE_VARRAY_STRUCT_ALLOC macro which is pretty similar to > VMSTATE_STRUCT_VARRAY_POINTER_INT32 but it can alloc memory for migratign > array on the destination side. > > This defines VMS_ALLOC flag for a field. > > This changes vmstate_base_addr() to do the allocation when receiving > migration.
Juan, Peter? No hurry, just pinging in order not to forget :) Thanks! > > Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> > --- > include/migration/vmstate.h | 11 +++++++++++ > vmstate.c | 13 ++++++++++--- > 2 files changed, 21 insertions(+), 3 deletions(-) > > diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h > index 7e45048..e794694 100644 > --- a/include/migration/vmstate.h > +++ b/include/migration/vmstate.h > @@ -101,6 +101,7 @@ enum VMStateFlags { > VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/ > VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/ > VMS_MUST_EXIST = 0x1000, /* Field must exist in input */ > + VMS_ALLOC = 0x2000, /* Alloc a buffer on the destination */ > }; > > typedef struct { > @@ -429,6 +430,16 @@ extern const VMStateInfo vmstate_info_bitmap; > .offset = offsetof(_state, _field), \ > } > > +#define VMSTATE_STRUCT_VARRAY_ALLOC(_field, _state, _field_num, _version, > _vmsd, _type) {\ > + .name = (stringify(_field)), \ > + .version_id = (_version), \ > + .vmsd = &(_vmsd), \ > + .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \ > + .size = sizeof(_type), \ > + .flags = VMS_STRUCT|VMS_VARRAY_INT32|VMS_ALLOC|VMS_POINTER, \ > + .offset = vmstate_offset_pointer(_state, _field, _type), \ > +} > + > #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, > _size) { \ > .name = (stringify(_field)), \ > .version_id = (_version), \ > diff --git a/vmstate.c b/vmstate.c > index b5882fa..fb95e39 100644 > --- a/vmstate.c > +++ b/vmstate.c > @@ -43,11 +43,18 @@ static int vmstate_size(void *opaque, VMStateField *field) > return size; > } > > -static void *vmstate_base_addr(void *opaque, VMStateField *field) > +static void *vmstate_base_addr(void *opaque, VMStateField *field, bool alloc) > { > void *base_addr = opaque + field->offset; > > if (field->flags & VMS_POINTER) { > + if (alloc && (field->flags & VMS_ALLOC)) { > + int n_elems = vmstate_n_elems(opaque, field); > + if (n_elems) { > + *((void **)base_addr + field->start) = g_malloc_n(n_elems, > + > field->size); > + } > + } > base_addr = *(void **)base_addr + field->start; > } > > @@ -81,7 +88,7 @@ int vmstate_load_state(QEMUFile *f, const > VMStateDescription *vmsd, > field->field_exists(opaque, version_id)) || > (!field->field_exists && > field->version_id <= version_id)) { > - void *base_addr = vmstate_base_addr(opaque, field); > + void *base_addr = vmstate_base_addr(opaque, field, true); > int i, n_elems = vmstate_n_elems(opaque, field); > int size = vmstate_size(opaque, field); > > @@ -131,7 +138,7 @@ void vmstate_save_state(QEMUFile *f, const > VMStateDescription *vmsd, > while (field->name) { > if (!field->field_exists || > field->field_exists(opaque, vmsd->version_id)) { > - void *base_addr = vmstate_base_addr(opaque, field); > + void *base_addr = vmstate_base_addr(opaque, field, false); > int i, n_elems = vmstate_n_elems(opaque, field); > int size = vmstate_size(opaque, field); > > -- Alexey