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