Message ID | 20230622131846.1f5fabb1@mobian (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3] multifd: Add colo support | expand |
copy hailiang. On Thu, Jun 22, 2023 at 01:18:46PM +0200, Lukas Straub wrote: > Like in the normal ram_load() path, put the received pages into the > colo cache and mark the pages in the bitmap so that they will be > flushed to the guest later. > > Signed-off-by: Juan Quintela <quintela@redhat.com> > Signed-off-by: Lukas Straub <lukasstraub2@web.de> > --- > migration/meson.build | 1 + > migration/multifd-colo.c | 53 ++++++++++++++++++++++++++++++++++++++++ > migration/multifd-colo.h | 24 ++++++++++++++++++ > migration/multifd.c | 5 ++++ > 4 files changed, 83 insertions(+) > create mode 100644 migration/multifd-colo.c > create mode 100644 migration/multifd-colo.h > > diff --git a/migration/meson.build b/migration/meson.build > index 1ae28523a1..063e0e0a8c 100644 > --- a/migration/meson.build > +++ b/migration/meson.build > @@ -21,6 +21,7 @@ system_ss.add(files( > 'migration.c', > 'multifd.c', > 'multifd-zlib.c', > + 'multifd-colo.c', > 'ram-compress.c', > 'options.c', > 'postcopy-ram.c', > diff --git a/migration/multifd-colo.c b/migration/multifd-colo.c > new file mode 100644 > index 0000000000..4872dc6d01 > --- /dev/null > +++ b/migration/multifd-colo.c > @@ -0,0 +1,53 @@ > +/* > + * multifd colo implementation > + * > + * Copyright (c) Lukas Straub <lukasstraub2@web.de> > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + */ > + > +#include "qemu/osdep.h" > +#include "exec/target_page.h" > +#include "exec/ramblock.h" > +#include "qemu/error-report.h" > +#include "qapi/error.h" > +#include "ram.h" > +#include "multifd.h" > +#include "options.h" > +#include "io/channel-socket.h" > +#include "migration/colo.h" > +#include "multifd-colo.h" > + > +void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p) > +{ > + if (!migrate_colo()) > + return; > + > + assert(p->block->colo_cache); > + > + /* > + * While we're still in precopy state (not yet in colo state), we copy > + * received pages to both guest and cache. No need to set dirty bits, > + * since guest and cache memory are in sync. > + */ > + if (migration_incoming_in_colo_state()) { > + colo_record_bitmap(p->block, p->normal, p->normal_num); > + } > + p->host = p->block->colo_cache; > +} > + > +void multifd_colo_process_recv_pages(MultiFDRecvParams *p) > +{ > + if (!migrate_colo()) > + return; > + > + if (!migration_incoming_in_colo_state()) { > + for (int i = 0; i < p->normal_num; i++) { > + void *guest = p->block->host + p->normal[i]; > + void *cache = p->host + p->normal[i]; > + memcpy(guest, cache, p->page_size); > + } > + } > + p->host = p->block->host; > +} > diff --git a/migration/multifd-colo.h b/migration/multifd-colo.h > new file mode 100644 > index 0000000000..58920a0583 > --- /dev/null > +++ b/migration/multifd-colo.h > @@ -0,0 +1,24 @@ > +/* > + * multifd colo header > + * > + * Copyright (c) Lukas Straub <lukasstraub2@web.de> > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + */ > + > +#ifndef QEMU_MIGRATION_MULTIFD_COLO_H > +#define QEMU_MIGRATION_MULTIFD_COLO_H > + > +#ifdef CONFIG_REPLICATION > + > +void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p); > +void multifd_colo_process_recv_pages(MultiFDRecvParams *p); > + > +#else > + > +static inline void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p) {} > +static inline void multifd_colo_process_recv_pages(MultiFDRecvParams *p) {} > + > +#endif > +#endif > diff --git a/migration/multifd.c b/migration/multifd.c > index 3387d8277f..6b031c1fd2 100644 > --- a/migration/multifd.c > +++ b/migration/multifd.c > @@ -25,6 +25,7 @@ > #include "qemu-file.h" > #include "trace.h" > #include "multifd.h" > +#include "multifd-colo.h" > #include "threadinfo.h" > #include "options.h" > #include "qemu/yank.h" > @@ -1134,10 +1135,14 @@ static void *multifd_recv_thread(void *opaque) > qemu_mutex_unlock(&p->mutex); > > if (p->normal_num) { > + multifd_colo_prepare_recv_pages(p); > + > ret = multifd_recv_state->ops->recv_pages(p, &local_err); > if (ret != 0) { > break; > } > + > + multifd_colo_process_recv_pages(p); > } > > if (flags & MULTIFD_FLAG_SYNC) { > -- > 2.39.2
diff --git a/migration/meson.build b/migration/meson.build index 1ae28523a1..063e0e0a8c 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -21,6 +21,7 @@ system_ss.add(files( 'migration.c', 'multifd.c', 'multifd-zlib.c', + 'multifd-colo.c', 'ram-compress.c', 'options.c', 'postcopy-ram.c', diff --git a/migration/multifd-colo.c b/migration/multifd-colo.c new file mode 100644 index 0000000000..4872dc6d01 --- /dev/null +++ b/migration/multifd-colo.c @@ -0,0 +1,53 @@ +/* + * multifd colo implementation + * + * Copyright (c) Lukas Straub <lukasstraub2@web.de> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "exec/target_page.h" +#include "exec/ramblock.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "ram.h" +#include "multifd.h" +#include "options.h" +#include "io/channel-socket.h" +#include "migration/colo.h" +#include "multifd-colo.h" + +void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p) +{ + if (!migrate_colo()) + return; + + assert(p->block->colo_cache); + + /* + * While we're still in precopy state (not yet in colo state), we copy + * received pages to both guest and cache. No need to set dirty bits, + * since guest and cache memory are in sync. + */ + if (migration_incoming_in_colo_state()) { + colo_record_bitmap(p->block, p->normal, p->normal_num); + } + p->host = p->block->colo_cache; +} + +void multifd_colo_process_recv_pages(MultiFDRecvParams *p) +{ + if (!migrate_colo()) + return; + + if (!migration_incoming_in_colo_state()) { + for (int i = 0; i < p->normal_num; i++) { + void *guest = p->block->host + p->normal[i]; + void *cache = p->host + p->normal[i]; + memcpy(guest, cache, p->page_size); + } + } + p->host = p->block->host; +} diff --git a/migration/multifd-colo.h b/migration/multifd-colo.h new file mode 100644 index 0000000000..58920a0583 --- /dev/null +++ b/migration/multifd-colo.h @@ -0,0 +1,24 @@ +/* + * multifd colo header + * + * Copyright (c) Lukas Straub <lukasstraub2@web.de> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_MIGRATION_MULTIFD_COLO_H +#define QEMU_MIGRATION_MULTIFD_COLO_H + +#ifdef CONFIG_REPLICATION + +void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p); +void multifd_colo_process_recv_pages(MultiFDRecvParams *p); + +#else + +static inline void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p) {} +static inline void multifd_colo_process_recv_pages(MultiFDRecvParams *p) {} + +#endif +#endif diff --git a/migration/multifd.c b/migration/multifd.c index 3387d8277f..6b031c1fd2 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -25,6 +25,7 @@ #include "qemu-file.h" #include "trace.h" #include "multifd.h" +#include "multifd-colo.h" #include "threadinfo.h" #include "options.h" #include "qemu/yank.h" @@ -1134,10 +1135,14 @@ static void *multifd_recv_thread(void *opaque) qemu_mutex_unlock(&p->mutex); if (p->normal_num) { + multifd_colo_prepare_recv_pages(p); + ret = multifd_recv_state->ops->recv_pages(p, &local_err); if (ret != 0) { break; } + + multifd_colo_process_recv_pages(p); } if (flags & MULTIFD_FLAG_SYNC) {