1*40c9471eSFabiano Rosas /* 2*40c9471eSFabiano Rosas * Multifd RAM migration without compression 3*40c9471eSFabiano Rosas * 4*40c9471eSFabiano Rosas * Copyright (c) 2019-2020 Red Hat Inc 5*40c9471eSFabiano Rosas * 6*40c9471eSFabiano Rosas * Authors: 7*40c9471eSFabiano Rosas * Juan Quintela <quintela@redhat.com> 8*40c9471eSFabiano Rosas * 9*40c9471eSFabiano Rosas * This work is licensed under the terms of the GNU GPL, version 2 or later. 10*40c9471eSFabiano Rosas * See the COPYING file in the top-level directory. 11*40c9471eSFabiano Rosas */ 12*40c9471eSFabiano Rosas 13*40c9471eSFabiano Rosas #include "qemu/osdep.h" 14*40c9471eSFabiano Rosas #include "exec/ramblock.h" 15*40c9471eSFabiano Rosas #include "exec/target_page.h" 16*40c9471eSFabiano Rosas #include "file.h" 17*40c9471eSFabiano Rosas #include "multifd.h" 18*40c9471eSFabiano Rosas #include "options.h" 19*40c9471eSFabiano Rosas #include "qapi/error.h" 20*40c9471eSFabiano Rosas #include "qemu/error-report.h" 21*40c9471eSFabiano Rosas #include "trace.h" 22*40c9471eSFabiano Rosas 23*40c9471eSFabiano Rosas static MultiFDSendData *multifd_ram_send; 24*40c9471eSFabiano Rosas 25*40c9471eSFabiano Rosas size_t multifd_ram_payload_size(void) 26*40c9471eSFabiano Rosas { 27*40c9471eSFabiano Rosas uint32_t n = multifd_ram_page_count(); 28*40c9471eSFabiano Rosas 29*40c9471eSFabiano Rosas /* 30*40c9471eSFabiano Rosas * We keep an array of page offsets at the end of MultiFDPages_t, 31*40c9471eSFabiano Rosas * add space for it in the allocation. 32*40c9471eSFabiano Rosas */ 33*40c9471eSFabiano Rosas return sizeof(MultiFDPages_t) + n * sizeof(ram_addr_t); 34*40c9471eSFabiano Rosas } 35*40c9471eSFabiano Rosas 36*40c9471eSFabiano Rosas void multifd_ram_save_setup(void) 37*40c9471eSFabiano Rosas { 38*40c9471eSFabiano Rosas multifd_ram_send = multifd_send_data_alloc(); 39*40c9471eSFabiano Rosas } 40*40c9471eSFabiano Rosas 41*40c9471eSFabiano Rosas void multifd_ram_save_cleanup(void) 42*40c9471eSFabiano Rosas { 43*40c9471eSFabiano Rosas g_free(multifd_ram_send); 44*40c9471eSFabiano Rosas multifd_ram_send = NULL; 45*40c9471eSFabiano Rosas } 46*40c9471eSFabiano Rosas 47*40c9471eSFabiano Rosas static void multifd_set_file_bitmap(MultiFDSendParams *p) 48*40c9471eSFabiano Rosas { 49*40c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram; 50*40c9471eSFabiano Rosas 51*40c9471eSFabiano Rosas assert(pages->block); 52*40c9471eSFabiano Rosas 53*40c9471eSFabiano Rosas for (int i = 0; i < pages->normal_num; i++) { 54*40c9471eSFabiano Rosas ramblock_set_file_bmap_atomic(pages->block, pages->offset[i], true); 55*40c9471eSFabiano Rosas } 56*40c9471eSFabiano Rosas 57*40c9471eSFabiano Rosas for (int i = pages->normal_num; i < pages->num; i++) { 58*40c9471eSFabiano Rosas ramblock_set_file_bmap_atomic(pages->block, pages->offset[i], false); 59*40c9471eSFabiano Rosas } 60*40c9471eSFabiano Rosas } 61*40c9471eSFabiano Rosas 62*40c9471eSFabiano Rosas static int multifd_nocomp_send_setup(MultiFDSendParams *p, Error **errp) 63*40c9471eSFabiano Rosas { 64*40c9471eSFabiano Rosas uint32_t page_count = multifd_ram_page_count(); 65*40c9471eSFabiano Rosas 66*40c9471eSFabiano Rosas if (migrate_zero_copy_send()) { 67*40c9471eSFabiano Rosas p->write_flags |= QIO_CHANNEL_WRITE_FLAG_ZERO_COPY; 68*40c9471eSFabiano Rosas } 69*40c9471eSFabiano Rosas 70*40c9471eSFabiano Rosas if (!migrate_mapped_ram()) { 71*40c9471eSFabiano Rosas /* We need one extra place for the packet header */ 72*40c9471eSFabiano Rosas p->iov = g_new0(struct iovec, page_count + 1); 73*40c9471eSFabiano Rosas } else { 74*40c9471eSFabiano Rosas p->iov = g_new0(struct iovec, page_count); 75*40c9471eSFabiano Rosas } 76*40c9471eSFabiano Rosas 77*40c9471eSFabiano Rosas return 0; 78*40c9471eSFabiano Rosas } 79*40c9471eSFabiano Rosas 80*40c9471eSFabiano Rosas static void multifd_nocomp_send_cleanup(MultiFDSendParams *p, Error **errp) 81*40c9471eSFabiano Rosas { 82*40c9471eSFabiano Rosas g_free(p->iov); 83*40c9471eSFabiano Rosas p->iov = NULL; 84*40c9471eSFabiano Rosas return; 85*40c9471eSFabiano Rosas } 86*40c9471eSFabiano Rosas 87*40c9471eSFabiano Rosas static void multifd_send_prepare_iovs(MultiFDSendParams *p) 88*40c9471eSFabiano Rosas { 89*40c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram; 90*40c9471eSFabiano Rosas uint32_t page_size = multifd_ram_page_size(); 91*40c9471eSFabiano Rosas 92*40c9471eSFabiano Rosas for (int i = 0; i < pages->normal_num; i++) { 93*40c9471eSFabiano Rosas p->iov[p->iovs_num].iov_base = pages->block->host + pages->offset[i]; 94*40c9471eSFabiano Rosas p->iov[p->iovs_num].iov_len = page_size; 95*40c9471eSFabiano Rosas p->iovs_num++; 96*40c9471eSFabiano Rosas } 97*40c9471eSFabiano Rosas 98*40c9471eSFabiano Rosas p->next_packet_size = pages->normal_num * page_size; 99*40c9471eSFabiano Rosas } 100*40c9471eSFabiano Rosas 101*40c9471eSFabiano Rosas static int multifd_nocomp_send_prepare(MultiFDSendParams *p, Error **errp) 102*40c9471eSFabiano Rosas { 103*40c9471eSFabiano Rosas bool use_zero_copy_send = migrate_zero_copy_send(); 104*40c9471eSFabiano Rosas int ret; 105*40c9471eSFabiano Rosas 106*40c9471eSFabiano Rosas multifd_send_zero_page_detect(p); 107*40c9471eSFabiano Rosas 108*40c9471eSFabiano Rosas if (migrate_mapped_ram()) { 109*40c9471eSFabiano Rosas multifd_send_prepare_iovs(p); 110*40c9471eSFabiano Rosas multifd_set_file_bitmap(p); 111*40c9471eSFabiano Rosas 112*40c9471eSFabiano Rosas return 0; 113*40c9471eSFabiano Rosas } 114*40c9471eSFabiano Rosas 115*40c9471eSFabiano Rosas if (!use_zero_copy_send) { 116*40c9471eSFabiano Rosas /* 117*40c9471eSFabiano Rosas * Only !zerocopy needs the header in IOV; zerocopy will 118*40c9471eSFabiano Rosas * send it separately. 119*40c9471eSFabiano Rosas */ 120*40c9471eSFabiano Rosas multifd_send_prepare_header(p); 121*40c9471eSFabiano Rosas } 122*40c9471eSFabiano Rosas 123*40c9471eSFabiano Rosas multifd_send_prepare_iovs(p); 124*40c9471eSFabiano Rosas p->flags |= MULTIFD_FLAG_NOCOMP; 125*40c9471eSFabiano Rosas 126*40c9471eSFabiano Rosas multifd_send_fill_packet(p); 127*40c9471eSFabiano Rosas 128*40c9471eSFabiano Rosas if (use_zero_copy_send) { 129*40c9471eSFabiano Rosas /* Send header first, without zerocopy */ 130*40c9471eSFabiano Rosas ret = qio_channel_write_all(p->c, (void *)p->packet, 131*40c9471eSFabiano Rosas p->packet_len, errp); 132*40c9471eSFabiano Rosas if (ret != 0) { 133*40c9471eSFabiano Rosas return -1; 134*40c9471eSFabiano Rosas } 135*40c9471eSFabiano Rosas } 136*40c9471eSFabiano Rosas 137*40c9471eSFabiano Rosas return 0; 138*40c9471eSFabiano Rosas } 139*40c9471eSFabiano Rosas 140*40c9471eSFabiano Rosas static int multifd_nocomp_recv_setup(MultiFDRecvParams *p, Error **errp) 141*40c9471eSFabiano Rosas { 142*40c9471eSFabiano Rosas p->iov = g_new0(struct iovec, multifd_ram_page_count()); 143*40c9471eSFabiano Rosas return 0; 144*40c9471eSFabiano Rosas } 145*40c9471eSFabiano Rosas 146*40c9471eSFabiano Rosas static void multifd_nocomp_recv_cleanup(MultiFDRecvParams *p) 147*40c9471eSFabiano Rosas { 148*40c9471eSFabiano Rosas g_free(p->iov); 149*40c9471eSFabiano Rosas p->iov = NULL; 150*40c9471eSFabiano Rosas } 151*40c9471eSFabiano Rosas 152*40c9471eSFabiano Rosas static int multifd_nocomp_recv(MultiFDRecvParams *p, Error **errp) 153*40c9471eSFabiano Rosas { 154*40c9471eSFabiano Rosas uint32_t flags; 155*40c9471eSFabiano Rosas 156*40c9471eSFabiano Rosas if (migrate_mapped_ram()) { 157*40c9471eSFabiano Rosas return multifd_file_recv_data(p, errp); 158*40c9471eSFabiano Rosas } 159*40c9471eSFabiano Rosas 160*40c9471eSFabiano Rosas flags = p->flags & MULTIFD_FLAG_COMPRESSION_MASK; 161*40c9471eSFabiano Rosas 162*40c9471eSFabiano Rosas if (flags != MULTIFD_FLAG_NOCOMP) { 163*40c9471eSFabiano Rosas error_setg(errp, "multifd %u: flags received %x flags expected %x", 164*40c9471eSFabiano Rosas p->id, flags, MULTIFD_FLAG_NOCOMP); 165*40c9471eSFabiano Rosas return -1; 166*40c9471eSFabiano Rosas } 167*40c9471eSFabiano Rosas 168*40c9471eSFabiano Rosas multifd_recv_zero_page_process(p); 169*40c9471eSFabiano Rosas 170*40c9471eSFabiano Rosas if (!p->normal_num) { 171*40c9471eSFabiano Rosas return 0; 172*40c9471eSFabiano Rosas } 173*40c9471eSFabiano Rosas 174*40c9471eSFabiano Rosas for (int i = 0; i < p->normal_num; i++) { 175*40c9471eSFabiano Rosas p->iov[i].iov_base = p->host + p->normal[i]; 176*40c9471eSFabiano Rosas p->iov[i].iov_len = multifd_ram_page_size(); 177*40c9471eSFabiano Rosas ramblock_recv_bitmap_set_offset(p->block, p->normal[i]); 178*40c9471eSFabiano Rosas } 179*40c9471eSFabiano Rosas return qio_channel_readv_all(p->c, p->iov, p->normal_num, errp); 180*40c9471eSFabiano Rosas } 181*40c9471eSFabiano Rosas 182*40c9471eSFabiano Rosas static void multifd_pages_reset(MultiFDPages_t *pages) 183*40c9471eSFabiano Rosas { 184*40c9471eSFabiano Rosas /* 185*40c9471eSFabiano Rosas * We don't need to touch offset[] array, because it will be 186*40c9471eSFabiano Rosas * overwritten later when reused. 187*40c9471eSFabiano Rosas */ 188*40c9471eSFabiano Rosas pages->num = 0; 189*40c9471eSFabiano Rosas pages->normal_num = 0; 190*40c9471eSFabiano Rosas pages->block = NULL; 191*40c9471eSFabiano Rosas } 192*40c9471eSFabiano Rosas 193*40c9471eSFabiano Rosas void multifd_ram_fill_packet(MultiFDSendParams *p) 194*40c9471eSFabiano Rosas { 195*40c9471eSFabiano Rosas MultiFDPacket_t *packet = p->packet; 196*40c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram; 197*40c9471eSFabiano Rosas uint32_t zero_num = pages->num - pages->normal_num; 198*40c9471eSFabiano Rosas 199*40c9471eSFabiano Rosas packet->pages_alloc = cpu_to_be32(multifd_ram_page_count()); 200*40c9471eSFabiano Rosas packet->normal_pages = cpu_to_be32(pages->normal_num); 201*40c9471eSFabiano Rosas packet->zero_pages = cpu_to_be32(zero_num); 202*40c9471eSFabiano Rosas 203*40c9471eSFabiano Rosas if (pages->block) { 204*40c9471eSFabiano Rosas strncpy(packet->ramblock, pages->block->idstr, 256); 205*40c9471eSFabiano Rosas } 206*40c9471eSFabiano Rosas 207*40c9471eSFabiano Rosas for (int i = 0; i < pages->num; i++) { 208*40c9471eSFabiano Rosas /* there are architectures where ram_addr_t is 32 bit */ 209*40c9471eSFabiano Rosas uint64_t temp = pages->offset[i]; 210*40c9471eSFabiano Rosas 211*40c9471eSFabiano Rosas packet->offset[i] = cpu_to_be64(temp); 212*40c9471eSFabiano Rosas } 213*40c9471eSFabiano Rosas 214*40c9471eSFabiano Rosas trace_multifd_send_ram_fill(p->id, pages->normal_num, 215*40c9471eSFabiano Rosas zero_num); 216*40c9471eSFabiano Rosas } 217*40c9471eSFabiano Rosas 218*40c9471eSFabiano Rosas int multifd_ram_unfill_packet(MultiFDRecvParams *p, Error **errp) 219*40c9471eSFabiano Rosas { 220*40c9471eSFabiano Rosas MultiFDPacket_t *packet = p->packet; 221*40c9471eSFabiano Rosas uint32_t page_count = multifd_ram_page_count(); 222*40c9471eSFabiano Rosas uint32_t page_size = multifd_ram_page_size(); 223*40c9471eSFabiano Rosas int i; 224*40c9471eSFabiano Rosas 225*40c9471eSFabiano Rosas packet->pages_alloc = be32_to_cpu(packet->pages_alloc); 226*40c9471eSFabiano Rosas /* 227*40c9471eSFabiano Rosas * If we received a packet that is 100 times bigger than expected 228*40c9471eSFabiano Rosas * just stop migration. It is a magic number. 229*40c9471eSFabiano Rosas */ 230*40c9471eSFabiano Rosas if (packet->pages_alloc > page_count) { 231*40c9471eSFabiano Rosas error_setg(errp, "multifd: received packet " 232*40c9471eSFabiano Rosas "with size %u and expected a size of %u", 233*40c9471eSFabiano Rosas packet->pages_alloc, page_count) ; 234*40c9471eSFabiano Rosas return -1; 235*40c9471eSFabiano Rosas } 236*40c9471eSFabiano Rosas 237*40c9471eSFabiano Rosas p->normal_num = be32_to_cpu(packet->normal_pages); 238*40c9471eSFabiano Rosas if (p->normal_num > packet->pages_alloc) { 239*40c9471eSFabiano Rosas error_setg(errp, "multifd: received packet " 240*40c9471eSFabiano Rosas "with %u normal pages and expected maximum pages are %u", 241*40c9471eSFabiano Rosas p->normal_num, packet->pages_alloc) ; 242*40c9471eSFabiano Rosas return -1; 243*40c9471eSFabiano Rosas } 244*40c9471eSFabiano Rosas 245*40c9471eSFabiano Rosas p->zero_num = be32_to_cpu(packet->zero_pages); 246*40c9471eSFabiano Rosas if (p->zero_num > packet->pages_alloc - p->normal_num) { 247*40c9471eSFabiano Rosas error_setg(errp, "multifd: received packet " 248*40c9471eSFabiano Rosas "with %u zero pages and expected maximum zero pages are %u", 249*40c9471eSFabiano Rosas p->zero_num, packet->pages_alloc - p->normal_num) ; 250*40c9471eSFabiano Rosas return -1; 251*40c9471eSFabiano Rosas } 252*40c9471eSFabiano Rosas 253*40c9471eSFabiano Rosas if (p->normal_num == 0 && p->zero_num == 0) { 254*40c9471eSFabiano Rosas return 0; 255*40c9471eSFabiano Rosas } 256*40c9471eSFabiano Rosas 257*40c9471eSFabiano Rosas /* make sure that ramblock is 0 terminated */ 258*40c9471eSFabiano Rosas packet->ramblock[255] = 0; 259*40c9471eSFabiano Rosas p->block = qemu_ram_block_by_name(packet->ramblock); 260*40c9471eSFabiano Rosas if (!p->block) { 261*40c9471eSFabiano Rosas error_setg(errp, "multifd: unknown ram block %s", 262*40c9471eSFabiano Rosas packet->ramblock); 263*40c9471eSFabiano Rosas return -1; 264*40c9471eSFabiano Rosas } 265*40c9471eSFabiano Rosas 266*40c9471eSFabiano Rosas p->host = p->block->host; 267*40c9471eSFabiano Rosas for (i = 0; i < p->normal_num; i++) { 268*40c9471eSFabiano Rosas uint64_t offset = be64_to_cpu(packet->offset[i]); 269*40c9471eSFabiano Rosas 270*40c9471eSFabiano Rosas if (offset > (p->block->used_length - page_size)) { 271*40c9471eSFabiano Rosas error_setg(errp, "multifd: offset too long %" PRIu64 272*40c9471eSFabiano Rosas " (max " RAM_ADDR_FMT ")", 273*40c9471eSFabiano Rosas offset, p->block->used_length); 274*40c9471eSFabiano Rosas return -1; 275*40c9471eSFabiano Rosas } 276*40c9471eSFabiano Rosas p->normal[i] = offset; 277*40c9471eSFabiano Rosas } 278*40c9471eSFabiano Rosas 279*40c9471eSFabiano Rosas for (i = 0; i < p->zero_num; i++) { 280*40c9471eSFabiano Rosas uint64_t offset = be64_to_cpu(packet->offset[p->normal_num + i]); 281*40c9471eSFabiano Rosas 282*40c9471eSFabiano Rosas if (offset > (p->block->used_length - page_size)) { 283*40c9471eSFabiano Rosas error_setg(errp, "multifd: offset too long %" PRIu64 284*40c9471eSFabiano Rosas " (max " RAM_ADDR_FMT ")", 285*40c9471eSFabiano Rosas offset, p->block->used_length); 286*40c9471eSFabiano Rosas return -1; 287*40c9471eSFabiano Rosas } 288*40c9471eSFabiano Rosas p->zero[i] = offset; 289*40c9471eSFabiano Rosas } 290*40c9471eSFabiano Rosas 291*40c9471eSFabiano Rosas return 0; 292*40c9471eSFabiano Rosas } 293*40c9471eSFabiano Rosas 294*40c9471eSFabiano Rosas static inline bool multifd_queue_empty(MultiFDPages_t *pages) 295*40c9471eSFabiano Rosas { 296*40c9471eSFabiano Rosas return pages->num == 0; 297*40c9471eSFabiano Rosas } 298*40c9471eSFabiano Rosas 299*40c9471eSFabiano Rosas static inline bool multifd_queue_full(MultiFDPages_t *pages) 300*40c9471eSFabiano Rosas { 301*40c9471eSFabiano Rosas return pages->num == multifd_ram_page_count(); 302*40c9471eSFabiano Rosas } 303*40c9471eSFabiano Rosas 304*40c9471eSFabiano Rosas static inline void multifd_enqueue(MultiFDPages_t *pages, ram_addr_t offset) 305*40c9471eSFabiano Rosas { 306*40c9471eSFabiano Rosas pages->offset[pages->num++] = offset; 307*40c9471eSFabiano Rosas } 308*40c9471eSFabiano Rosas 309*40c9471eSFabiano Rosas /* Returns true if enqueue successful, false otherwise */ 310*40c9471eSFabiano Rosas bool multifd_queue_page(RAMBlock *block, ram_addr_t offset) 311*40c9471eSFabiano Rosas { 312*40c9471eSFabiano Rosas MultiFDPages_t *pages; 313*40c9471eSFabiano Rosas 314*40c9471eSFabiano Rosas retry: 315*40c9471eSFabiano Rosas pages = &multifd_ram_send->u.ram; 316*40c9471eSFabiano Rosas 317*40c9471eSFabiano Rosas if (multifd_payload_empty(multifd_ram_send)) { 318*40c9471eSFabiano Rosas multifd_pages_reset(pages); 319*40c9471eSFabiano Rosas multifd_set_payload_type(multifd_ram_send, MULTIFD_PAYLOAD_RAM); 320*40c9471eSFabiano Rosas } 321*40c9471eSFabiano Rosas 322*40c9471eSFabiano Rosas /* If the queue is empty, we can already enqueue now */ 323*40c9471eSFabiano Rosas if (multifd_queue_empty(pages)) { 324*40c9471eSFabiano Rosas pages->block = block; 325*40c9471eSFabiano Rosas multifd_enqueue(pages, offset); 326*40c9471eSFabiano Rosas return true; 327*40c9471eSFabiano Rosas } 328*40c9471eSFabiano Rosas 329*40c9471eSFabiano Rosas /* 330*40c9471eSFabiano Rosas * Not empty, meanwhile we need a flush. It can because of either: 331*40c9471eSFabiano Rosas * 332*40c9471eSFabiano Rosas * (1) The page is not on the same ramblock of previous ones, or, 333*40c9471eSFabiano Rosas * (2) The queue is full. 334*40c9471eSFabiano Rosas * 335*40c9471eSFabiano Rosas * After flush, always retry. 336*40c9471eSFabiano Rosas */ 337*40c9471eSFabiano Rosas if (pages->block != block || multifd_queue_full(pages)) { 338*40c9471eSFabiano Rosas if (!multifd_send(&multifd_ram_send)) { 339*40c9471eSFabiano Rosas return false; 340*40c9471eSFabiano Rosas } 341*40c9471eSFabiano Rosas goto retry; 342*40c9471eSFabiano Rosas } 343*40c9471eSFabiano Rosas 344*40c9471eSFabiano Rosas /* Not empty, and we still have space, do it! */ 345*40c9471eSFabiano Rosas multifd_enqueue(pages, offset); 346*40c9471eSFabiano Rosas return true; 347*40c9471eSFabiano Rosas } 348*40c9471eSFabiano Rosas 349*40c9471eSFabiano Rosas int multifd_ram_flush_and_sync(void) 350*40c9471eSFabiano Rosas { 351*40c9471eSFabiano Rosas if (!migrate_multifd()) { 352*40c9471eSFabiano Rosas return 0; 353*40c9471eSFabiano Rosas } 354*40c9471eSFabiano Rosas 355*40c9471eSFabiano Rosas if (!multifd_payload_empty(multifd_ram_send)) { 356*40c9471eSFabiano Rosas if (!multifd_send(&multifd_ram_send)) { 357*40c9471eSFabiano Rosas error_report("%s: multifd_send fail", __func__); 358*40c9471eSFabiano Rosas return -1; 359*40c9471eSFabiano Rosas } 360*40c9471eSFabiano Rosas } 361*40c9471eSFabiano Rosas 362*40c9471eSFabiano Rosas return multifd_send_sync_main(); 363*40c9471eSFabiano Rosas } 364*40c9471eSFabiano Rosas 365*40c9471eSFabiano Rosas bool multifd_send_prepare_common(MultiFDSendParams *p) 366*40c9471eSFabiano Rosas { 367*40c9471eSFabiano Rosas MultiFDPages_t *pages = &p->data->u.ram; 368*40c9471eSFabiano Rosas multifd_send_zero_page_detect(p); 369*40c9471eSFabiano Rosas 370*40c9471eSFabiano Rosas if (!pages->normal_num) { 371*40c9471eSFabiano Rosas p->next_packet_size = 0; 372*40c9471eSFabiano Rosas return false; 373*40c9471eSFabiano Rosas } 374*40c9471eSFabiano Rosas 375*40c9471eSFabiano Rosas multifd_send_prepare_header(p); 376*40c9471eSFabiano Rosas 377*40c9471eSFabiano Rosas return true; 378*40c9471eSFabiano Rosas } 379*40c9471eSFabiano Rosas 380*40c9471eSFabiano Rosas static MultiFDMethods multifd_nocomp_ops = { 381*40c9471eSFabiano Rosas .send_setup = multifd_nocomp_send_setup, 382*40c9471eSFabiano Rosas .send_cleanup = multifd_nocomp_send_cleanup, 383*40c9471eSFabiano Rosas .send_prepare = multifd_nocomp_send_prepare, 384*40c9471eSFabiano Rosas .recv_setup = multifd_nocomp_recv_setup, 385*40c9471eSFabiano Rosas .recv_cleanup = multifd_nocomp_recv_cleanup, 386*40c9471eSFabiano Rosas .recv = multifd_nocomp_recv 387*40c9471eSFabiano Rosas }; 388*40c9471eSFabiano Rosas 389*40c9471eSFabiano Rosas static void multifd_nocomp_register(void) 390*40c9471eSFabiano Rosas { 391*40c9471eSFabiano Rosas multifd_register_ops(MULTIFD_COMPRESSION_NONE, &multifd_nocomp_ops); 392*40c9471eSFabiano Rosas } 393*40c9471eSFabiano Rosas 394*40c9471eSFabiano Rosas migration_init(multifd_nocomp_register); 395