From: Fabiano Rosas <farosas@suse.de>
To: "Maciej S. Szmigiero" <mail@maciej.szmigiero.name>,
Peter Xu <peterx@redhat.com>
Cc: "Alex Williamson" <alex.williamson@redhat.com>,
"Cédric Le Goater" <clg@redhat.com>,
"Eric Blake" <eblake@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Daniel P . Berrangé" <berrange@redhat.com>,
"Avihai Horon" <avihaih@nvidia.com>,
"Joao Martins" <joao.m.martins@oracle.com>,
qemu-devel@nongnu.org
Subject: Re: [PATCH v2 09/17] migration/multifd: Device state transfer support - receive side
Date: Fri, 30 Aug 2024 17:22:13 -0300 [thread overview]
Message-ID: <87ttf1n4lm.fsf@suse.de> (raw)
In-Reply-To: <84141182083a8417c25b4d82a9c4b6228b22ac67.1724701542.git.maciej.szmigiero@oracle.com>
"Maciej S. Szmigiero" <mail@maciej.szmigiero.name> writes:
> From: "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>
>
> Add a basic support for receiving device state via multifd channels -
> channels that are shared with RAM transfers.
>
> To differentiate between a device state and a RAM packet the packet
> header is read first.
>
> Depending whether MULTIFD_FLAG_DEVICE_STATE flag is present or not in the
> packet header either device state (MultiFDPacketDeviceState_t) or RAM
> data (existing MultiFDPacket_t) is then read.
>
> The received device state data is provided to
> qemu_loadvm_load_state_buffer() function for processing in the
> device's load_state_buffer handler.
>
> Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
> ---
> migration/multifd.c | 127 +++++++++++++++++++++++++++++++++++++-------
> migration/multifd.h | 31 ++++++++++-
> 2 files changed, 138 insertions(+), 20 deletions(-)
>
> diff --git a/migration/multifd.c b/migration/multifd.c
> index b06a9fab500e..d5a8e5a9c9b5 100644
> --- a/migration/multifd.c
> +++ b/migration/multifd.c
> @@ -21,6 +21,7 @@
> #include "file.h"
> #include "migration.h"
> #include "migration-stats.h"
> +#include "savevm.h"
> #include "socket.h"
> #include "tls.h"
> #include "qemu-file.h"
> @@ -209,10 +210,10 @@ void multifd_send_fill_packet(MultiFDSendParams *p)
>
> memset(packet, 0, p->packet_len);
>
> - packet->magic = cpu_to_be32(MULTIFD_MAGIC);
> - packet->version = cpu_to_be32(MULTIFD_VERSION);
> + packet->hdr.magic = cpu_to_be32(MULTIFD_MAGIC);
> + packet->hdr.version = cpu_to_be32(MULTIFD_VERSION);
>
> - packet->flags = cpu_to_be32(p->flags);
> + packet->hdr.flags = cpu_to_be32(p->flags);
> packet->next_packet_size = cpu_to_be32(p->next_packet_size);
>
> packet_num = qatomic_fetch_inc(&multifd_send_state->packet_num);
> @@ -228,31 +229,49 @@ void multifd_send_fill_packet(MultiFDSendParams *p)
> p->flags, p->next_packet_size);
> }
>
> -static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
> +static int multifd_recv_unfill_packet_header(MultiFDRecvParams *p,
> + MultiFDPacketHdr_t *hdr,
> + Error **errp)
> {
> - MultiFDPacket_t *packet = p->packet;
> - int ret = 0;
> -
> - packet->magic = be32_to_cpu(packet->magic);
> - if (packet->magic != MULTIFD_MAGIC) {
> + hdr->magic = be32_to_cpu(hdr->magic);
> + if (hdr->magic != MULTIFD_MAGIC) {
> error_setg(errp, "multifd: received packet "
> "magic %x and expected magic %x",
> - packet->magic, MULTIFD_MAGIC);
> + hdr->magic, MULTIFD_MAGIC);
> return -1;
> }
>
> - packet->version = be32_to_cpu(packet->version);
> - if (packet->version != MULTIFD_VERSION) {
> + hdr->version = be32_to_cpu(hdr->version);
> + if (hdr->version != MULTIFD_VERSION) {
> error_setg(errp, "multifd: received packet "
> "version %u and expected version %u",
> - packet->version, MULTIFD_VERSION);
> + hdr->version, MULTIFD_VERSION);
> return -1;
> }
>
> - p->flags = be32_to_cpu(packet->flags);
> + p->flags = be32_to_cpu(hdr->flags);
> +
> + return 0;
> +}
> +
> +static int multifd_recv_unfill_packet_device_state(MultiFDRecvParams *p,
> + Error **errp)
> +{
> + MultiFDPacketDeviceState_t *packet = p->packet_dev_state;
> +
> + packet->instance_id = be32_to_cpu(packet->instance_id);
> + p->next_packet_size = be32_to_cpu(packet->next_packet_size);
> +
> + return 0;
> +}
> +
> +static int multifd_recv_unfill_packet_ram(MultiFDRecvParams *p, Error **errp)
> +{
> + MultiFDPacket_t *packet = p->packet;
> + int ret = 0;
> +
> p->next_packet_size = be32_to_cpu(packet->next_packet_size);
> p->packet_num = be64_to_cpu(packet->packet_num);
> - p->packets_recved++;
>
> if (!(p->flags & MULTIFD_FLAG_SYNC)) {
> ret = multifd_ram_unfill_packet(p, errp);
> @@ -264,6 +283,19 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
> return ret;
> }
>
> +static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
> +{
> + p->packets_recved++;
> +
> + if (p->flags & MULTIFD_FLAG_DEVICE_STATE) {
> + return multifd_recv_unfill_packet_device_state(p, errp);
> + } else {
> + return multifd_recv_unfill_packet_ram(p, errp);
> + }
> +
> + g_assert_not_reached();
> +}
> +
> static bool multifd_send_should_exit(void)
> {
> return qatomic_read(&multifd_send_state->exiting);
> @@ -1014,6 +1046,7 @@ static void multifd_recv_cleanup_channel(MultiFDRecvParams *p)
> p->packet_len = 0;
> g_free(p->packet);
> p->packet = NULL;
> + g_clear_pointer(&p->packet_dev_state, g_free);
> g_free(p->normal);
> p->normal = NULL;
> g_free(p->zero);
> @@ -1126,8 +1159,13 @@ static void *multifd_recv_thread(void *opaque)
> rcu_register_thread();
>
> while (true) {
> + MultiFDPacketHdr_t hdr;
> uint32_t flags = 0;
> + bool is_device_state = false;
> bool has_data = false;
> + uint8_t *pkt_buf;
> + size_t pkt_len;
> +
> p->normal_num = 0;
>
> if (use_packets) {
> @@ -1135,8 +1173,28 @@ static void *multifd_recv_thread(void *opaque)
> break;
> }
>
> - ret = qio_channel_read_all_eof(p->c, (void *)p->packet,
> - p->packet_len, &local_err);
> + ret = qio_channel_read_all_eof(p->c, (void *)&hdr,
> + sizeof(hdr), &local_err);
> + if (ret == 0 || ret == -1) { /* 0: EOF -1: Error */
> + break;
> + }
> +
> + ret = multifd_recv_unfill_packet_header(p, &hdr, &local_err);
> + if (ret) {
> + break;
> + }
> +
> + is_device_state = p->flags & MULTIFD_FLAG_DEVICE_STATE;
> + if (is_device_state) {
> + pkt_buf = (uint8_t *)p->packet_dev_state + sizeof(hdr);
> + pkt_len = sizeof(*p->packet_dev_state) - sizeof(hdr);
> + } else {
> + pkt_buf = (uint8_t *)p->packet + sizeof(hdr);
> + pkt_len = p->packet_len - sizeof(hdr);
> + }
Should we have made the packet an union as well? Would simplify these
sorts of operations. Not sure I want to start messing with that at this
point to be honest. But OTOH, look at this...
> +
> + ret = qio_channel_read_all_eof(p->c, (char *)pkt_buf, pkt_len,
> + &local_err);
> if (ret == 0 || ret == -1) { /* 0: EOF -1: Error */
> break;
> }
> @@ -1181,8 +1239,33 @@ static void *multifd_recv_thread(void *opaque)
> has_data = !!p->data->size;
> }
>
> - if (has_data) {
> - ret = multifd_recv_state->ops->recv(p, &local_err);
> + if (!is_device_state) {
> + if (has_data) {
> + ret = multifd_recv_state->ops->recv(p, &local_err);
> + if (ret != 0) {
> + break;
> + }
> + }
> + } else {
> + g_autofree char *idstr = NULL;
> + g_autofree char *dev_state_buf = NULL;
> +
> + assert(use_packets);
> +
> + if (p->next_packet_size > 0) {
> + dev_state_buf = g_malloc(p->next_packet_size);
> +
> + ret = qio_channel_read_all(p->c, dev_state_buf, p->next_packet_size, &local_err);
> + if (ret != 0) {
> + break;
> + }
> + }
What's the use case for !next_packet_size and still call
load_state_buffer below? I can't see it.
...because I would suggest to set has_data up there with
p->next_packet_size:
if (use_packets) {
...
has_data = p->next_packet_size || p->zero_num;
} else {
...
has_data = !!p->data_size;
}
and this whole block would be:
if (has_data) {
if (is_device_state) {
multifd_device_state_recv(p, &local_err);
} else {
ret = multifd_recv_state->ops->recv(p, &local_err);
}
}
> +
> + idstr = g_strndup(p->packet_dev_state->idstr, sizeof(p->packet_dev_state->idstr));
> + ret = qemu_loadvm_load_state_buffer(idstr,
> + p->packet_dev_state->instance_id,
> + dev_state_buf, p->next_packet_size,
> + &local_err);
> if (ret != 0) {
> break;
> }
> @@ -1190,6 +1273,11 @@ static void *multifd_recv_thread(void *opaque)
>
> if (use_packets) {
> if (flags & MULTIFD_FLAG_SYNC) {
> + if (is_device_state) {
> + error_setg(&local_err, "multifd: received SYNC device state packet");
> + break;
> + }
assert(!is_device_state) enough?
> +
> qemu_sem_post(&multifd_recv_state->sem_sync);
> qemu_sem_wait(&p->sem_sync);
> }
> @@ -1258,6 +1346,7 @@ int multifd_recv_setup(Error **errp)
> p->packet_len = sizeof(MultiFDPacket_t)
> + sizeof(uint64_t) * page_count;
> p->packet = g_malloc0(p->packet_len);
> + p->packet_dev_state = g_malloc0(sizeof(*p->packet_dev_state));
> }
> p->name = g_strdup_printf("mig/dst/recv_%d", i);
> p->normal = g_new0(ram_addr_t, page_count);
> diff --git a/migration/multifd.h b/migration/multifd.h
> index a3e35196d179..a8f3e4838c01 100644
> --- a/migration/multifd.h
> +++ b/migration/multifd.h
> @@ -45,6 +45,12 @@ MultiFDRecvData *multifd_get_recv_data(void);
> #define MULTIFD_FLAG_QPL (4 << 1)
> #define MULTIFD_FLAG_UADK (8 << 1)
>
> +/*
> + * If set it means that this packet contains device state
> + * (MultiFDPacketDeviceState_t), not RAM data (MultiFDPacket_t).
> + */
> +#define MULTIFD_FLAG_DEVICE_STATE (1 << 4)
Overlaps with UADK. I assume on purpose because device_state doesn't
support compression? Might be worth a comment.
> +
> /* This value needs to be a multiple of qemu_target_page_size() */
> #define MULTIFD_PACKET_SIZE (512 * 1024)
>
> @@ -52,6 +58,11 @@ typedef struct {
> uint32_t magic;
> uint32_t version;
> uint32_t flags;
> +} __attribute__((packed)) MultiFDPacketHdr_t;
> +
> +typedef struct {
> + MultiFDPacketHdr_t hdr;
> +
> /* maximum number of allocated pages */
> uint32_t pages_alloc;
> /* non zero pages */
> @@ -72,6 +83,16 @@ typedef struct {
> uint64_t offset[];
> } __attribute__((packed)) MultiFDPacket_t;
>
> +typedef struct {
> + MultiFDPacketHdr_t hdr;
> +
> + char idstr[256] QEMU_NONSTRING;
> + uint32_t instance_id;
> +
> + /* size of the next packet that contains the actual data */
> + uint32_t next_packet_size;
> +} __attribute__((packed)) MultiFDPacketDeviceState_t;
> +
> typedef struct {
> /* number of used pages */
> uint32_t num;
> @@ -89,6 +110,13 @@ 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,
> @@ -204,8 +232,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_dev_state;
> /* size of the next packet that contains pages */
> uint32_t next_packet_size;
> /* packets received through this channel */
next prev parent reply other threads:[~2024-08-30 20:23 UTC|newest]
Thread overview: 128+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-27 17:54 [PATCH v2 00/17] Multifd 🔀 device state transfer support with VFIO consumer Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 01/17] vfio/migration: Add save_{iterate, complete_precopy}_started trace events Maciej S. Szmigiero
2024-09-05 13:08 ` [PATCH v2 01/17] vfio/migration: Add save_{iterate,complete_precopy}_started " Avihai Horon
2024-09-09 18:04 ` Maciej S. Szmigiero
2024-09-11 14:50 ` Avihai Horon
2024-08-27 17:54 ` [PATCH v2 02/17] migration/ram: Add load start trace event Maciej S. Szmigiero
2024-08-28 18:44 ` Fabiano Rosas
2024-08-28 20:21 ` Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 03/17] migration/multifd: Zero p->flags before starting filling a packet Maciej S. Szmigiero
2024-08-28 18:50 ` Fabiano Rosas
2024-09-09 15:41 ` Peter Xu
2024-08-27 17:54 ` [PATCH v2 04/17] thread-pool: Add a DestroyNotify parameter to thread_pool_submit{, _aio)() Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 05/17] thread-pool: Implement non-AIO (generic) pool support Maciej S. Szmigiero
2024-09-02 22:07 ` Fabiano Rosas
2024-09-03 12:02 ` Maciej S. Szmigiero
2024-09-03 14:26 ` Fabiano Rosas
2024-09-03 18:14 ` Maciej S. Szmigiero
2024-09-03 13:55 ` Stefan Hajnoczi
2024-09-03 16:54 ` Maciej S. Szmigiero
2024-09-03 19:04 ` Stefan Hajnoczi
2024-09-09 16:45 ` Peter Xu
2024-09-09 18:38 ` Maciej S. Szmigiero
2024-09-09 19:12 ` Peter Xu
2024-09-09 19:16 ` Maciej S. Szmigiero
2024-09-09 19:24 ` Peter Xu
2024-08-27 17:54 ` [PATCH v2 06/17] migration: Add save_live_complete_precopy_{begin, end} handlers Maciej S. Szmigiero
2024-08-28 19:03 ` [PATCH v2 06/17] migration: Add save_live_complete_precopy_{begin,end} handlers Fabiano Rosas
2024-09-05 13:45 ` Avihai Horon
2024-09-09 17:59 ` Peter Xu
2024-09-09 18:32 ` Maciej S. Szmigiero
2024-09-09 19:08 ` Peter Xu
2024-09-09 19:32 ` Peter Xu
2024-09-19 19:48 ` Maciej S. Szmigiero
2024-09-19 19:47 ` Maciej S. Szmigiero
2024-09-19 20:54 ` Peter Xu
2024-09-20 15:22 ` Maciej S. Szmigiero
2024-09-20 16:08 ` Peter Xu
2024-09-09 18:05 ` Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 07/17] migration: Add qemu_loadvm_load_state_buffer() and its handler Maciej S. Szmigiero
2024-08-30 19:05 ` Fabiano Rosas
2024-09-05 14:15 ` Avihai Horon
2024-09-09 18:05 ` Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 08/17] migration: Add load_finish handler and associated functions Maciej S. Szmigiero
2024-08-30 19:28 ` Fabiano Rosas
2024-09-05 15:13 ` Avihai Horon
2024-09-09 18:05 ` Maciej S. Szmigiero
2024-09-09 20:03 ` Peter Xu
2024-09-19 19:49 ` Maciej S. Szmigiero
2024-09-19 21:11 ` Peter Xu
2024-09-20 15:23 ` Maciej S. Szmigiero
2024-09-20 16:45 ` Peter Xu
2024-09-26 22:34 ` Maciej S. Szmigiero
2024-09-27 0:53 ` Peter Xu
2024-09-30 19:25 ` Maciej S. Szmigiero
2024-09-30 21:57 ` Peter Xu
2024-10-01 20:41 ` Maciej S. Szmigiero
2024-10-01 21:30 ` Peter Xu
2024-10-02 20:11 ` Maciej S. Szmigiero
2024-10-02 21:25 ` Peter Xu
2024-10-03 20:34 ` Maciej S. Szmigiero
2024-10-03 21:17 ` Peter Xu
2024-08-27 17:54 ` [PATCH v2 09/17] migration/multifd: Device state transfer support - receive side Maciej S. Szmigiero
2024-08-30 20:22 ` Fabiano Rosas [this message]
2024-09-02 20:12 ` Maciej S. Szmigiero
2024-09-03 14:42 ` Fabiano Rosas
2024-09-03 18:41 ` Maciej S. Szmigiero
2024-09-09 19:52 ` Peter Xu
2024-09-19 19:49 ` Maciej S. Szmigiero
2024-09-05 16:47 ` Avihai Horon
2024-09-09 18:05 ` Maciej S. Szmigiero
2024-09-12 8:13 ` Avihai Horon
2024-09-12 13:52 ` Fabiano Rosas
2024-09-19 19:59 ` Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 10/17] migration/multifd: Convert multifd_send()::next_channel to atomic Maciej S. Szmigiero
2024-08-30 18:13 ` Fabiano Rosas
2024-09-02 20:11 ` Maciej S. Szmigiero
2024-09-03 15:01 ` Fabiano Rosas
2024-09-03 20:04 ` Maciej S. Szmigiero
2024-09-10 14:13 ` Peter Xu
2024-08-27 17:54 ` [PATCH v2 11/17] migration/multifd: Add an explicit MultiFDSendData destructor Maciej S. Szmigiero
2024-08-30 13:12 ` Fabiano Rosas
2024-08-27 17:54 ` [PATCH v2 12/17] migration/multifd: Device state transfer support - send side Maciej S. Szmigiero
2024-08-29 0:41 ` Fabiano Rosas
2024-08-29 20:03 ` Maciej S. Szmigiero
2024-08-30 13:02 ` Fabiano Rosas
2024-09-09 19:40 ` Peter Xu
2024-09-19 19:50 ` Maciej S. Szmigiero
2024-09-10 19:48 ` Peter Xu
2024-09-12 18:43 ` Fabiano Rosas
2024-09-13 0:23 ` Peter Xu
2024-09-13 13:21 ` Fabiano Rosas
2024-09-13 14:19 ` Peter Xu
2024-09-13 15:04 ` Fabiano Rosas
2024-09-13 15:22 ` Peter Xu
2024-09-13 18:26 ` Fabiano Rosas
2024-09-17 15:39 ` Peter Xu
2024-09-17 17:07 ` Cédric Le Goater
2024-09-17 17:50 ` Peter Xu
2024-09-19 19:51 ` Maciej S. Szmigiero
2024-09-19 19:49 ` Maciej S. Szmigiero
2024-09-19 21:17 ` Peter Xu
2024-09-20 15:23 ` Maciej S. Szmigiero
2024-09-20 17:09 ` Peter Xu
2024-09-10 16:06 ` Peter Xu
2024-09-19 19:49 ` Maciej S. Szmigiero
2024-09-19 21:18 ` Peter Xu
2024-08-27 17:54 ` [PATCH v2 13/17] migration/multifd: Add migration_has_device_state_support() Maciej S. Szmigiero
2024-08-30 18:55 ` Fabiano Rosas
2024-09-02 20:11 ` Maciej S. Szmigiero
2024-09-03 15:09 ` Fabiano Rosas
2024-08-27 17:54 ` [PATCH v2 14/17] migration: Add save_live_complete_precopy_thread handler Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 15/17] vfio/migration: Multifd device state transfer support - receive side Maciej S. Szmigiero
2024-09-09 8:55 ` Avihai Horon
2024-09-09 18:06 ` Maciej S. Szmigiero
2024-09-12 8:20 ` Avihai Horon
2024-09-12 8:45 ` Cédric Le Goater
2024-08-27 17:54 ` [PATCH v2 16/17] vfio/migration: Add x-migration-multifd-transfer VFIO property Maciej S. Szmigiero
2024-08-27 17:54 ` [PATCH v2 17/17] vfio/migration: Multifd device state transfer support - send side Maciej S. Szmigiero
2024-09-09 11:41 ` Avihai Horon
2024-09-09 18:07 ` Maciej S. Szmigiero
2024-09-12 8:26 ` Avihai Horon
2024-09-12 8:57 ` Cédric Le Goater
2024-08-28 20:46 ` [PATCH v2 00/17] Multifd 🔀 device state transfer support with VFIO consumer Fabiano Rosas
2024-08-28 21:58 ` Maciej S. Szmigiero
2024-08-29 0:51 ` Fabiano Rosas
2024-08-29 20:02 ` Maciej S. Szmigiero
2024-10-11 13:58 ` Cédric Le Goater
2024-10-15 21:12 ` Maciej S. Szmigiero
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ttf1n4lm.fsf@suse.de \
--to=farosas@suse.de \
--cc=alex.williamson@redhat.com \
--cc=armbru@redhat.com \
--cc=avihaih@nvidia.com \
--cc=berrange@redhat.com \
--cc=clg@redhat.com \
--cc=eblake@redhat.com \
--cc=joao.m.martins@oracle.com \
--cc=mail@maciej.szmigiero.name \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.