@@ -16,11 +16,6 @@ static QemuMutex queue_job_mutex;
static MultiFDSendData *device_state_send;
-size_t multifd_device_state_payload_size(void)
-{
- return sizeof(MultiFDDeviceState_t);
-}
-
void multifd_device_state_send_setup(void)
{
qemu_mutex_init(&queue_job_mutex);
@@ -23,15 +23,14 @@
static MultiFDSendData *multifd_ram_send;
-size_t multifd_ram_payload_size(void)
+void multifd_ram_payload_alloc(MultiFDPages_t *pages)
{
- uint32_t n = multifd_ram_page_count();
+ pages->offset = g_new0(ram_addr_t, multifd_ram_page_count());
+}
- /*
- * We keep an array of page offsets at the end of MultiFDPages_t,
- * add space for it in the allocation.
- */
- return sizeof(MultiFDPages_t) + n * sizeof(ram_addr_t);
+void multifd_ram_payload_free(MultiFDPages_t *pages)
+{
+ g_clear_pointer(&pages->offset, g_free);
}
void multifd_ram_save_setup(void)
@@ -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));
-
- /*
- * 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);
+ multifd_ram_payload_alloc(&new->u.ram);
+ /* Device state allocates its payload on-demand */
- 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);
}
@@ -99,9 +99,13 @@ typedef struct {
uint32_t num;
/* number of normal pages */
uint32_t normal_num;
+ /*
+ * Pointer to the ramblock. NOTE: it's caller's responsibility to make
+ * sure the pointer is always valid!
+ */
RAMBlock *block;
- /* offset of each page */
- ram_addr_t offset[];
+ /* offset array of each page, managed by multifd */
+ ram_addr_t *offset;
} MultiFDPages_t;
struct MultiFDRecvData {
@@ -124,7 +128,7 @@ typedef enum {
MULTIFD_PAYLOAD_DEVICE_STATE,
} MultiFDPayloadType;
-typedef union MultiFDPayload {
+typedef struct MultiFDPayload {
MultiFDPages_t ram;
MultiFDDeviceState_t device_state;
} MultiFDPayload;
@@ -373,11 +377,11 @@ static inline uint32_t multifd_ram_page_count(void)
void multifd_ram_save_setup(void);
void multifd_ram_save_cleanup(void);
int multifd_ram_flush_and_sync(void);
-size_t multifd_ram_payload_size(void);
+void multifd_ram_payload_alloc(MultiFDPages_t *pages);
+void multifd_ram_payload_free(MultiFDPages_t *pages);
void multifd_ram_fill_packet(MultiFDSendParams *p);
int multifd_ram_unfill_packet(MultiFDRecvParams *p, Error **errp);
-size_t multifd_device_state_payload_size(void);
void multifd_device_state_send_setup(void);
void multifd_device_state_clear(MultiFDDeviceState_t *device_state);
void multifd_device_state_send_cleanup(void);