migration/multifd: Device state transfer support - send side

A new function multifd_queue_device_state() is provided for device to queue
its state for transmission via a multifd channel.

Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Link: https://lore.kernel.org/qemu-devel/ebd55768d3e5fecb5eb3f197bad9c0c07e5bc084.1741124640.git.maciej.szmigiero@oracle.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
Maciej S. Szmigiero 2025-03-04 23:03:41 +01:00 committed by Cédric Le Goater
parent 7ecfab1ddd
commit 0525b91a0b
6 changed files with 197 additions and 16 deletions

View file

@ -127,13 +127,22 @@ struct MultiFDRecvData {
off_t file_offset;
};
typedef struct {
char *idstr;
uint32_t instance_id;
char *buf;
size_t buf_len;
} MultiFDDeviceState_t;
typedef enum {
MULTIFD_PAYLOAD_NONE,
MULTIFD_PAYLOAD_RAM,
MULTIFD_PAYLOAD_DEVICE_STATE,
} MultiFDPayloadType;
typedef union MultiFDPayload {
MultiFDPages_t ram;
MultiFDDeviceState_t device_state;
} MultiFDPayload;
struct MultiFDSendData {
@ -146,6 +155,11 @@ static inline bool multifd_payload_empty(MultiFDSendData *data)
return data->type == MULTIFD_PAYLOAD_NONE;
}
static inline bool multifd_payload_device_state(MultiFDSendData *data)
{
return data->type == MULTIFD_PAYLOAD_DEVICE_STATE;
}
static inline void multifd_set_payload_type(MultiFDSendData *data,
MultiFDPayloadType type)
{
@ -198,8 +212,9 @@ typedef struct {
/* thread local variables. No locking required */
/* pointer to the packet */
/* pointers to the possible packet types */
MultiFDPacket_t *packet;
MultiFDPacketDeviceState_t *packet_device_state;
/* size of the next packet that contains pages */
uint32_t next_packet_size;
/* packets sent through this channel */
@ -358,13 +373,6 @@ bool multifd_send_prepare_common(MultiFDSendParams *p);
void multifd_send_zero_page_detect(MultiFDSendParams *p);
void multifd_recv_zero_page_process(MultiFDRecvParams *p);
static inline void multifd_send_prepare_header(MultiFDSendParams *p)
{
p->iov[0].iov_len = p->packet_len;
p->iov[0].iov_base = p->packet;
p->iovs_num++;
}
void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc);
bool multifd_send(MultiFDSendData **send_data);
MultiFDSendData *multifd_send_data_alloc(void);
@ -389,4 +397,14 @@ bool multifd_ram_sync_per_section(void);
size_t multifd_ram_payload_size(void);
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_send_data_clear_device_state(MultiFDDeviceState_t *device_state);
void multifd_device_state_send_setup(void);
void multifd_device_state_send_cleanup(void);
void multifd_device_state_send_prepare(MultiFDSendParams *p);
#endif