140c9471eSFabiano Rosas /*
240c9471eSFabiano Rosas * Multifd RAM migration without compression
340c9471eSFabiano Rosas *
440c9471eSFabiano Rosas * Copyright (c) 2019-2020 Red Hat Inc
540c9471eSFabiano Rosas *
640c9471eSFabiano Rosas * Authors:
740c9471eSFabiano Rosas * Juan Quintela <quintela@redhat.com>
840c9471eSFabiano Rosas *
940c9471eSFabiano Rosas * This work is licensed under the terms of the GNU GPL, version 2 or later.
1040c9471eSFabiano Rosas * See the COPYING file in the top-level directory.
1140c9471eSFabiano Rosas */
1240c9471eSFabiano Rosas
1340c9471eSFabiano Rosas #include "qemu/osdep.h"
1440c9471eSFabiano Rosas #include "exec/ramblock.h"
1540c9471eSFabiano Rosas #include "exec/target_page.h"
1640c9471eSFabiano Rosas #include "file.h"
1740c9471eSFabiano Rosas #include "multifd.h"
1840c9471eSFabiano Rosas #include "options.h"
1940c9471eSFabiano Rosas #include "qapi/error.h"
20*68e0fca6SFabiano Rosas #include "qemu/cutils.h"
2140c9471eSFabiano Rosas #include "qemu/error-report.h"
2240c9471eSFabiano Rosas #include "trace.h"
2340c9471eSFabiano Rosas
2440c9471eSFabiano Rosas static MultiFDSendData *multifd_ram_send;
2540c9471eSFabiano Rosas
multifd_ram_payload_size(void)2640c9471eSFabiano Rosas size_t multifd_ram_payload_size(void)
2740c9471eSFabiano Rosas {
2840c9471eSFabiano Rosas uint32_t n = multifd_ram_page_count();
2940c9471eSFabiano Rosas
3040c9471eSFabiano Rosas /*
3140c9471eSFabiano Rosas * We keep an array of page offsets at the end of MultiFDPages_t,
3240c9471eSFabiano Rosas * add space for it in the allocation.
3340c9471eSFabiano Rosas */
3440c9471eSFabiano Rosas return sizeof(MultiFDPages_t) + n * sizeof(ram_addr_t);
3540c9471eSFabiano Rosas }
3640c9471eSFabiano Rosas
multifd_ram_save_setup(void)3740c9471eSFabiano Rosas void multifd_ram_save_setup(void)
3840c9471eSFabiano Rosas {
3940c9471eSFabiano Rosas multifd_ram_send = multifd_send_data_alloc();
4040c9471eSFabiano Rosas }
4140c9471eSFabiano Rosas
multifd_ram_save_cleanup(void)4240c9471eSFabiano Rosas void multifd_ram_save_cleanup(void)
4340c9471eSFabiano Rosas {
4440c9471eSFabiano Rosas g_free(multifd_ram_send);
4540c9471eSFabiano Rosas multifd_ram_send = NULL;
4640c9471eSFabiano Rosas }
4740c9471eSFabiano Rosas
multifd_set_file_bitmap(MultiFDSendParams * p)4840c9471eSFabiano Rosas static void multifd_set_file_bitmap(MultiFDSendParams *p)
4940c9471eSFabiano Rosas {
5040c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram;
5140c9471eSFabiano Rosas
5240c9471eSFabiano Rosas assert(pages->block);
5340c9471eSFabiano Rosas
5440c9471eSFabiano Rosas for (int i = 0; i < pages->normal_num; i++) {
5540c9471eSFabiano Rosas ramblock_set_file_bmap_atomic(pages->block, pages->offset[i], true);
5640c9471eSFabiano Rosas }
5740c9471eSFabiano Rosas
5840c9471eSFabiano Rosas for (int i = pages->normal_num; i < pages->num; i++) {
5940c9471eSFabiano Rosas ramblock_set_file_bmap_atomic(pages->block, pages->offset[i], false);
6040c9471eSFabiano Rosas }
6140c9471eSFabiano Rosas }
6240c9471eSFabiano Rosas
multifd_nocomp_send_setup(MultiFDSendParams * p,Error ** errp)6340c9471eSFabiano Rosas static int multifd_nocomp_send_setup(MultiFDSendParams *p, Error **errp)
6440c9471eSFabiano Rosas {
6540c9471eSFabiano Rosas uint32_t page_count = multifd_ram_page_count();
6640c9471eSFabiano Rosas
6740c9471eSFabiano Rosas if (migrate_zero_copy_send()) {
6840c9471eSFabiano Rosas p->write_flags |= QIO_CHANNEL_WRITE_FLAG_ZERO_COPY;
6940c9471eSFabiano Rosas }
7040c9471eSFabiano Rosas
7140c9471eSFabiano Rosas if (!migrate_mapped_ram()) {
7240c9471eSFabiano Rosas /* We need one extra place for the packet header */
7340c9471eSFabiano Rosas p->iov = g_new0(struct iovec, page_count + 1);
7440c9471eSFabiano Rosas } else {
7540c9471eSFabiano Rosas p->iov = g_new0(struct iovec, page_count);
7640c9471eSFabiano Rosas }
7740c9471eSFabiano Rosas
7840c9471eSFabiano Rosas return 0;
7940c9471eSFabiano Rosas }
8040c9471eSFabiano Rosas
multifd_nocomp_send_cleanup(MultiFDSendParams * p,Error ** errp)8140c9471eSFabiano Rosas static void multifd_nocomp_send_cleanup(MultiFDSendParams *p, Error **errp)
8240c9471eSFabiano Rosas {
8340c9471eSFabiano Rosas g_free(p->iov);
8440c9471eSFabiano Rosas p->iov = NULL;
8540c9471eSFabiano Rosas return;
8640c9471eSFabiano Rosas }
8740c9471eSFabiano Rosas
multifd_send_prepare_iovs(MultiFDSendParams * p)8840c9471eSFabiano Rosas static void multifd_send_prepare_iovs(MultiFDSendParams *p)
8940c9471eSFabiano Rosas {
9040c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram;
9140c9471eSFabiano Rosas uint32_t page_size = multifd_ram_page_size();
9240c9471eSFabiano Rosas
9340c9471eSFabiano Rosas for (int i = 0; i < pages->normal_num; i++) {
9440c9471eSFabiano Rosas p->iov[p->iovs_num].iov_base = pages->block->host + pages->offset[i];
9540c9471eSFabiano Rosas p->iov[p->iovs_num].iov_len = page_size;
9640c9471eSFabiano Rosas p->iovs_num++;
9740c9471eSFabiano Rosas }
9840c9471eSFabiano Rosas
9940c9471eSFabiano Rosas p->next_packet_size = pages->normal_num * page_size;
10040c9471eSFabiano Rosas }
10140c9471eSFabiano Rosas
multifd_nocomp_send_prepare(MultiFDSendParams * p,Error ** errp)10240c9471eSFabiano Rosas static int multifd_nocomp_send_prepare(MultiFDSendParams *p, Error **errp)
10340c9471eSFabiano Rosas {
10440c9471eSFabiano Rosas bool use_zero_copy_send = migrate_zero_copy_send();
10540c9471eSFabiano Rosas int ret;
10640c9471eSFabiano Rosas
10740c9471eSFabiano Rosas multifd_send_zero_page_detect(p);
10840c9471eSFabiano Rosas
10940c9471eSFabiano Rosas if (migrate_mapped_ram()) {
11040c9471eSFabiano Rosas multifd_send_prepare_iovs(p);
11140c9471eSFabiano Rosas multifd_set_file_bitmap(p);
11240c9471eSFabiano Rosas
11340c9471eSFabiano Rosas return 0;
11440c9471eSFabiano Rosas }
11540c9471eSFabiano Rosas
11640c9471eSFabiano Rosas if (!use_zero_copy_send) {
11740c9471eSFabiano Rosas /*
11840c9471eSFabiano Rosas * Only !zerocopy needs the header in IOV; zerocopy will
11940c9471eSFabiano Rosas * send it separately.
12040c9471eSFabiano Rosas */
12140c9471eSFabiano Rosas multifd_send_prepare_header(p);
12240c9471eSFabiano Rosas }
12340c9471eSFabiano Rosas
12440c9471eSFabiano Rosas multifd_send_prepare_iovs(p);
12540c9471eSFabiano Rosas p->flags |= MULTIFD_FLAG_NOCOMP;
12640c9471eSFabiano Rosas
12740c9471eSFabiano Rosas multifd_send_fill_packet(p);
12840c9471eSFabiano Rosas
12940c9471eSFabiano Rosas if (use_zero_copy_send) {
13040c9471eSFabiano Rosas /* Send header first, without zerocopy */
13140c9471eSFabiano Rosas ret = qio_channel_write_all(p->c, (void *)p->packet,
13240c9471eSFabiano Rosas p->packet_len, errp);
13340c9471eSFabiano Rosas if (ret != 0) {
13440c9471eSFabiano Rosas return -1;
13540c9471eSFabiano Rosas }
13640c9471eSFabiano Rosas }
13740c9471eSFabiano Rosas
13840c9471eSFabiano Rosas return 0;
13940c9471eSFabiano Rosas }
14040c9471eSFabiano Rosas
multifd_nocomp_recv_setup(MultiFDRecvParams * p,Error ** errp)14140c9471eSFabiano Rosas static int multifd_nocomp_recv_setup(MultiFDRecvParams *p, Error **errp)
14240c9471eSFabiano Rosas {
14340c9471eSFabiano Rosas p->iov = g_new0(struct iovec, multifd_ram_page_count());
14440c9471eSFabiano Rosas return 0;
14540c9471eSFabiano Rosas }
14640c9471eSFabiano Rosas
multifd_nocomp_recv_cleanup(MultiFDRecvParams * p)14740c9471eSFabiano Rosas static void multifd_nocomp_recv_cleanup(MultiFDRecvParams *p)
14840c9471eSFabiano Rosas {
14940c9471eSFabiano Rosas g_free(p->iov);
15040c9471eSFabiano Rosas p->iov = NULL;
15140c9471eSFabiano Rosas }
15240c9471eSFabiano Rosas
multifd_nocomp_recv(MultiFDRecvParams * p,Error ** errp)15340c9471eSFabiano Rosas static int multifd_nocomp_recv(MultiFDRecvParams *p, Error **errp)
15440c9471eSFabiano Rosas {
15540c9471eSFabiano Rosas uint32_t flags;
15640c9471eSFabiano Rosas
15740c9471eSFabiano Rosas if (migrate_mapped_ram()) {
15840c9471eSFabiano Rosas return multifd_file_recv_data(p, errp);
15940c9471eSFabiano Rosas }
16040c9471eSFabiano Rosas
16140c9471eSFabiano Rosas flags = p->flags & MULTIFD_FLAG_COMPRESSION_MASK;
16240c9471eSFabiano Rosas
16340c9471eSFabiano Rosas if (flags != MULTIFD_FLAG_NOCOMP) {
16440c9471eSFabiano Rosas error_setg(errp, "multifd %u: flags received %x flags expected %x",
16540c9471eSFabiano Rosas p->id, flags, MULTIFD_FLAG_NOCOMP);
16640c9471eSFabiano Rosas return -1;
16740c9471eSFabiano Rosas }
16840c9471eSFabiano Rosas
16940c9471eSFabiano Rosas multifd_recv_zero_page_process(p);
17040c9471eSFabiano Rosas
17140c9471eSFabiano Rosas if (!p->normal_num) {
17240c9471eSFabiano Rosas return 0;
17340c9471eSFabiano Rosas }
17440c9471eSFabiano Rosas
17540c9471eSFabiano Rosas for (int i = 0; i < p->normal_num; i++) {
17640c9471eSFabiano Rosas p->iov[i].iov_base = p->host + p->normal[i];
17740c9471eSFabiano Rosas p->iov[i].iov_len = multifd_ram_page_size();
17840c9471eSFabiano Rosas ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
17940c9471eSFabiano Rosas }
18040c9471eSFabiano Rosas return qio_channel_readv_all(p->c, p->iov, p->normal_num, errp);
18140c9471eSFabiano Rosas }
18240c9471eSFabiano Rosas
multifd_pages_reset(MultiFDPages_t * pages)18340c9471eSFabiano Rosas static void multifd_pages_reset(MultiFDPages_t *pages)
18440c9471eSFabiano Rosas {
18540c9471eSFabiano Rosas /*
18640c9471eSFabiano Rosas * We don't need to touch offset[] array, because it will be
18740c9471eSFabiano Rosas * overwritten later when reused.
18840c9471eSFabiano Rosas */
18940c9471eSFabiano Rosas pages->num = 0;
19040c9471eSFabiano Rosas pages->normal_num = 0;
19140c9471eSFabiano Rosas pages->block = NULL;
19240c9471eSFabiano Rosas }
19340c9471eSFabiano Rosas
multifd_ram_fill_packet(MultiFDSendParams * p)19440c9471eSFabiano Rosas void multifd_ram_fill_packet(MultiFDSendParams *p)
19540c9471eSFabiano Rosas {
19640c9471eSFabiano Rosas MultiFDPacket_t *packet = p->packet;
19740c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram;
19840c9471eSFabiano Rosas uint32_t zero_num = pages->num - pages->normal_num;
19940c9471eSFabiano Rosas
20040c9471eSFabiano Rosas packet->pages_alloc = cpu_to_be32(multifd_ram_page_count());
20140c9471eSFabiano Rosas packet->normal_pages = cpu_to_be32(pages->normal_num);
20240c9471eSFabiano Rosas packet->zero_pages = cpu_to_be32(zero_num);
20340c9471eSFabiano Rosas
20440c9471eSFabiano Rosas if (pages->block) {
205*68e0fca6SFabiano Rosas pstrcpy(packet->ramblock, sizeof(packet->ramblock),
206*68e0fca6SFabiano Rosas pages->block->idstr);
20740c9471eSFabiano Rosas }
20840c9471eSFabiano Rosas
20940c9471eSFabiano Rosas for (int i = 0; i < pages->num; i++) {
21040c9471eSFabiano Rosas /* there are architectures where ram_addr_t is 32 bit */
21140c9471eSFabiano Rosas uint64_t temp = pages->offset[i];
21240c9471eSFabiano Rosas
21340c9471eSFabiano Rosas packet->offset[i] = cpu_to_be64(temp);
21440c9471eSFabiano Rosas }
21540c9471eSFabiano Rosas
21640c9471eSFabiano Rosas trace_multifd_send_ram_fill(p->id, pages->normal_num,
21740c9471eSFabiano Rosas zero_num);
21840c9471eSFabiano Rosas }
21940c9471eSFabiano Rosas
multifd_ram_unfill_packet(MultiFDRecvParams * p,Error ** errp)22040c9471eSFabiano Rosas int multifd_ram_unfill_packet(MultiFDRecvParams *p, Error **errp)
22140c9471eSFabiano Rosas {
22240c9471eSFabiano Rosas MultiFDPacket_t *packet = p->packet;
22340c9471eSFabiano Rosas uint32_t page_count = multifd_ram_page_count();
22440c9471eSFabiano Rosas uint32_t page_size = multifd_ram_page_size();
22581b0ed8aSFabiano Rosas uint32_t pages_per_packet = be32_to_cpu(packet->pages_alloc);
22640c9471eSFabiano Rosas int i;
22740c9471eSFabiano Rosas
22881b0ed8aSFabiano Rosas if (pages_per_packet > page_count) {
22981b0ed8aSFabiano Rosas error_setg(errp, "multifd: received packet with %u pages, expected %u",
23081b0ed8aSFabiano Rosas pages_per_packet, page_count);
23140c9471eSFabiano Rosas return -1;
23240c9471eSFabiano Rosas }
23340c9471eSFabiano Rosas
23440c9471eSFabiano Rosas p->normal_num = be32_to_cpu(packet->normal_pages);
23581b0ed8aSFabiano Rosas if (p->normal_num > pages_per_packet) {
23681b0ed8aSFabiano Rosas error_setg(errp, "multifd: received packet with %u non-zero pages, "
23781b0ed8aSFabiano Rosas "which exceeds maximum expected pages %u",
23881b0ed8aSFabiano Rosas p->normal_num, pages_per_packet);
23940c9471eSFabiano Rosas return -1;
24040c9471eSFabiano Rosas }
24140c9471eSFabiano Rosas
24240c9471eSFabiano Rosas p->zero_num = be32_to_cpu(packet->zero_pages);
24381b0ed8aSFabiano Rosas if (p->zero_num > pages_per_packet - p->normal_num) {
24481b0ed8aSFabiano Rosas error_setg(errp,
24581b0ed8aSFabiano Rosas "multifd: received packet with %u zero pages, expected maximum %u",
24681b0ed8aSFabiano Rosas p->zero_num, pages_per_packet - p->normal_num);
24740c9471eSFabiano Rosas return -1;
24840c9471eSFabiano Rosas }
24940c9471eSFabiano Rosas
25040c9471eSFabiano Rosas if (p->normal_num == 0 && p->zero_num == 0) {
25140c9471eSFabiano Rosas return 0;
25240c9471eSFabiano Rosas }
25340c9471eSFabiano Rosas
25440c9471eSFabiano Rosas /* make sure that ramblock is 0 terminated */
25540c9471eSFabiano Rosas packet->ramblock[255] = 0;
25640c9471eSFabiano Rosas p->block = qemu_ram_block_by_name(packet->ramblock);
25740c9471eSFabiano Rosas if (!p->block) {
25840c9471eSFabiano Rosas error_setg(errp, "multifd: unknown ram block %s",
25940c9471eSFabiano Rosas packet->ramblock);
26040c9471eSFabiano Rosas return -1;
26140c9471eSFabiano Rosas }
26240c9471eSFabiano Rosas
26340c9471eSFabiano Rosas p->host = p->block->host;
26440c9471eSFabiano Rosas for (i = 0; i < p->normal_num; i++) {
26540c9471eSFabiano Rosas uint64_t offset = be64_to_cpu(packet->offset[i]);
26640c9471eSFabiano Rosas
26740c9471eSFabiano Rosas if (offset > (p->block->used_length - page_size)) {
26840c9471eSFabiano Rosas error_setg(errp, "multifd: offset too long %" PRIu64
26940c9471eSFabiano Rosas " (max " RAM_ADDR_FMT ")",
27040c9471eSFabiano Rosas offset, p->block->used_length);
27140c9471eSFabiano Rosas return -1;
27240c9471eSFabiano Rosas }
27340c9471eSFabiano Rosas p->normal[i] = offset;
27440c9471eSFabiano Rosas }
27540c9471eSFabiano Rosas
27640c9471eSFabiano Rosas for (i = 0; i < p->zero_num; i++) {
27740c9471eSFabiano Rosas uint64_t offset = be64_to_cpu(packet->offset[p->normal_num + i]);
27840c9471eSFabiano Rosas
27940c9471eSFabiano Rosas if (offset > (p->block->used_length - page_size)) {
28040c9471eSFabiano Rosas error_setg(errp, "multifd: offset too long %" PRIu64
28140c9471eSFabiano Rosas " (max " RAM_ADDR_FMT ")",
28240c9471eSFabiano Rosas offset, p->block->used_length);
28340c9471eSFabiano Rosas return -1;
28440c9471eSFabiano Rosas }
28540c9471eSFabiano Rosas p->zero[i] = offset;
28640c9471eSFabiano Rosas }
28740c9471eSFabiano Rosas
28840c9471eSFabiano Rosas return 0;
28940c9471eSFabiano Rosas }
29040c9471eSFabiano Rosas
multifd_queue_empty(MultiFDPages_t * pages)29140c9471eSFabiano Rosas static inline bool multifd_queue_empty(MultiFDPages_t *pages)
29240c9471eSFabiano Rosas {
29340c9471eSFabiano Rosas return pages->num == 0;
29440c9471eSFabiano Rosas }
29540c9471eSFabiano Rosas
multifd_queue_full(MultiFDPages_t * pages)29640c9471eSFabiano Rosas static inline bool multifd_queue_full(MultiFDPages_t *pages)
29740c9471eSFabiano Rosas {
29840c9471eSFabiano Rosas return pages->num == multifd_ram_page_count();
29940c9471eSFabiano Rosas }
30040c9471eSFabiano Rosas
multifd_enqueue(MultiFDPages_t * pages,ram_addr_t offset)30140c9471eSFabiano Rosas static inline void multifd_enqueue(MultiFDPages_t *pages, ram_addr_t offset)
30240c9471eSFabiano Rosas {
30340c9471eSFabiano Rosas pages->offset[pages->num++] = offset;
30440c9471eSFabiano Rosas }
30540c9471eSFabiano Rosas
30640c9471eSFabiano Rosas /* Returns true if enqueue successful, false otherwise */
multifd_queue_page(RAMBlock * block,ram_addr_t offset)30740c9471eSFabiano Rosas bool multifd_queue_page(RAMBlock *block, ram_addr_t offset)
30840c9471eSFabiano Rosas {
30940c9471eSFabiano Rosas MultiFDPages_t *pages;
31040c9471eSFabiano Rosas
31140c9471eSFabiano Rosas retry:
31240c9471eSFabiano Rosas pages = &multifd_ram_send->u.ram;
31340c9471eSFabiano Rosas
31440c9471eSFabiano Rosas if (multifd_payload_empty(multifd_ram_send)) {
31540c9471eSFabiano Rosas multifd_pages_reset(pages);
31640c9471eSFabiano Rosas multifd_set_payload_type(multifd_ram_send, MULTIFD_PAYLOAD_RAM);
31740c9471eSFabiano Rosas }
31840c9471eSFabiano Rosas
31940c9471eSFabiano Rosas /* If the queue is empty, we can already enqueue now */
32040c9471eSFabiano Rosas if (multifd_queue_empty(pages)) {
32140c9471eSFabiano Rosas pages->block = block;
32240c9471eSFabiano Rosas multifd_enqueue(pages, offset);
32340c9471eSFabiano Rosas return true;
32440c9471eSFabiano Rosas }
32540c9471eSFabiano Rosas
32640c9471eSFabiano Rosas /*
32740c9471eSFabiano Rosas * Not empty, meanwhile we need a flush. It can because of either:
32840c9471eSFabiano Rosas *
32940c9471eSFabiano Rosas * (1) The page is not on the same ramblock of previous ones, or,
33040c9471eSFabiano Rosas * (2) The queue is full.
33140c9471eSFabiano Rosas *
33240c9471eSFabiano Rosas * After flush, always retry.
33340c9471eSFabiano Rosas */
33440c9471eSFabiano Rosas if (pages->block != block || multifd_queue_full(pages)) {
33540c9471eSFabiano Rosas if (!multifd_send(&multifd_ram_send)) {
33640c9471eSFabiano Rosas return false;
33740c9471eSFabiano Rosas }
33840c9471eSFabiano Rosas goto retry;
33940c9471eSFabiano Rosas }
34040c9471eSFabiano Rosas
34140c9471eSFabiano Rosas /* Not empty, and we still have space, do it! */
34240c9471eSFabiano Rosas multifd_enqueue(pages, offset);
34340c9471eSFabiano Rosas return true;
34440c9471eSFabiano Rosas }
34540c9471eSFabiano Rosas
multifd_ram_flush_and_sync(void)34640c9471eSFabiano Rosas int multifd_ram_flush_and_sync(void)
34740c9471eSFabiano Rosas {
34840c9471eSFabiano Rosas if (!migrate_multifd()) {
34940c9471eSFabiano Rosas return 0;
35040c9471eSFabiano Rosas }
35140c9471eSFabiano Rosas
35240c9471eSFabiano Rosas if (!multifd_payload_empty(multifd_ram_send)) {
35340c9471eSFabiano Rosas if (!multifd_send(&multifd_ram_send)) {
35440c9471eSFabiano Rosas error_report("%s: multifd_send fail", __func__);
35540c9471eSFabiano Rosas return -1;
35640c9471eSFabiano Rosas }
35740c9471eSFabiano Rosas }
35840c9471eSFabiano Rosas
35940c9471eSFabiano Rosas return multifd_send_sync_main();
36040c9471eSFabiano Rosas }
36140c9471eSFabiano Rosas
multifd_send_prepare_common(MultiFDSendParams * p)36240c9471eSFabiano Rosas bool multifd_send_prepare_common(MultiFDSendParams *p)
36340c9471eSFabiano Rosas {
36440c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram;
36540c9471eSFabiano Rosas multifd_send_zero_page_detect(p);
36640c9471eSFabiano Rosas
36740c9471eSFabiano Rosas if (!pages->normal_num) {
36840c9471eSFabiano Rosas p->next_packet_size = 0;
36940c9471eSFabiano Rosas return false;
37040c9471eSFabiano Rosas }
37140c9471eSFabiano Rosas
37240c9471eSFabiano Rosas multifd_send_prepare_header(p);
37340c9471eSFabiano Rosas
37440c9471eSFabiano Rosas return true;
37540c9471eSFabiano Rosas }
37640c9471eSFabiano Rosas
377308d165cSFabiano Rosas static const MultiFDMethods multifd_nocomp_ops = {
37840c9471eSFabiano Rosas .send_setup = multifd_nocomp_send_setup,
37940c9471eSFabiano Rosas .send_cleanup = multifd_nocomp_send_cleanup,
38040c9471eSFabiano Rosas .send_prepare = multifd_nocomp_send_prepare,
38140c9471eSFabiano Rosas .recv_setup = multifd_nocomp_recv_setup,
38240c9471eSFabiano Rosas .recv_cleanup = multifd_nocomp_recv_cleanup,
38340c9471eSFabiano Rosas .recv = multifd_nocomp_recv
38440c9471eSFabiano Rosas };
38540c9471eSFabiano Rosas
multifd_nocomp_register(void)38640c9471eSFabiano Rosas static void multifd_nocomp_register(void)
38740c9471eSFabiano Rosas {
38840c9471eSFabiano Rosas multifd_register_ops(MULTIFD_COMPRESSION_NONE, &multifd_nocomp_ops);
38940c9471eSFabiano Rosas }
39040c9471eSFabiano Rosas
39140c9471eSFabiano Rosas migration_init(multifd_nocomp_register);
392