migration/multifd: Make MultiFDSendData a struct

The newly introduced device state buffer can be used for either storing
VFIO's read() raw data, but already also possible to store generic device
states.  After noticing that device states may not easily provide a max
buffer size (also the fact that RAM MultiFDPages_t after all also want to
have flexibility on managing offset[] array), it may not be a good idea to
stick with union on MultiFDSendData.. as it won't play well with such
flexibility.

Switch MultiFDSendData to a struct.

It won't consume a lot more space in reality, after all the real buffers
were already dynamically allocated, so it's so far only about the two
structs (pages, device_state) that will be duplicated, but they're small.

With this, we can remove the pretty hard to understand alloc size logic.
Because now we can allocate offset[] together with the SendData, and
properly free it when the SendData is freed.

[MSS: Make sure to clear possible device state payload before freeing
MultiFDSendData, remove placeholders for other patches not included]

Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Acked-by: Fabiano Rosas <farosas@suse.de>
Link: https://lore.kernel.org/qemu-devel/7b02baba8e6ddb23ef7c349d312b9b631db09d7e.1741124640.git.maciej.szmigiero@oracle.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
Peter Xu 2025-03-04 23:03:42 +01:00 committed by Cédric Le Goater
parent 0525b91a0b
commit 99fab22350
4 changed files with 22 additions and 36 deletions

View file

@ -105,26 +105,12 @@ struct {
MultiFDSendData *multifd_send_data_alloc(void)
{
size_t max_payload_size, size_minus_payload;
MultiFDSendData *new = g_new0(MultiFDSendData, 1);
/*
* MultiFDPages_t has a flexible array at the end, account for it
* when allocating MultiFDSendData. Use max() in case other types
* added to the union in the future are larger than
* (MultiFDPages_t + flex array).
*/
max_payload_size = MAX(multifd_ram_payload_size(),
multifd_device_state_payload_size());
max_payload_size = MAX(max_payload_size, sizeof(MultiFDPayload));
multifd_ram_payload_alloc(&new->u.ram);
/* Device state allocates its payload on-demand */
/*
* Account for any holes the compiler might insert. We can't pack
* the structure because that misaligns the members and triggers
* Waddress-of-packed-member.
*/
size_minus_payload = sizeof(MultiFDSendData) - sizeof(MultiFDPayload);
return g_malloc0(size_minus_payload + max_payload_size);
return new;
}
void multifd_send_data_clear(MultiFDSendData *data)
@ -151,8 +137,11 @@ void multifd_send_data_free(MultiFDSendData *data)
return;
}
/* This also free's device state payload */
multifd_send_data_clear(data);
multifd_ram_payload_free(&data->u.ram);
g_free(data);
}