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