* [PATCH v9 0/7] Allow to enable multifd and postcopy migration together @ 2025-04-11 11:45 Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 1/7] migration/multifd: move macros to multifd header Prasad Pandit ` (7 more replies) 0 siblings, 8 replies; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange, Prasad Pandit From: Prasad Pandit <pjp@fedoraproject.org> Hello, * This series (v9) does minor refactoring and reordering changes as suggested in the review of earlier series (v8). Also tried to reproduce/debug a qtest hang issue, but it could not be reproduced. From the shared stack traces it looked like Postcopy thread was preparing to finish before migrating all the pages. === 67/67 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 170.50s 81 subtests passed === v8: https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t * This series (v8) splits earlier patch-2 which enabled multifd and postcopy options together into two separate patches. One modifies the channel discovery in migration_ioc_process_incoming() function, and second one enables the multifd and postcopy migration together. It also adds the 'save_postcopy_prepare' savevm_state handler to enable different sections to take an action just before the Postcopy phase starts. Thank you Peter for these patches. === 67/67 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 152.66s 81 subtests passed === v7: https://lore.kernel.org/qemu-devel/20250228121749.553184-1-ppandit@redhat.com/T/#t * This series (v7) adds 'MULTIFD_RECV_SYNC' migration command. It is used to notify the destination migration thread to synchronise with the Multifd threads. This allows Multifd ('mig/dst/recv_x') threads on the destination to receive all their data, before they are shutdown. This series also updates the channel discovery function and qtests as suggested in the previous review comments. === 67/67 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 147.84s 81 subtests passed === v6: https://lore.kernel.org/qemu-devel/20250215123119.814345-1-ppandit@redhat.com/T/#t * This series (v6) shuts down Multifd threads before starting Postcopy migration. It helps to avoid an issue of multifd pages arriving late at the destination during Postcopy phase and corrupting the vCPU state. It also reorders the qtest patches and does some refactoring changes as suggested in previous review. === 67/67 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 161.35s 73 subtests passed === v5: https://lore.kernel.org/qemu-devel/20250205122712.229151-1-ppandit@redhat.com/T/#t * This series (v5) consolidates migration capabilities setting in one 'set_migration_capabilities()' function, thus simplifying test sources. It passes all migration tests. === 66/66 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 143.66s 71 subtests passed === v4: https://lore.kernel.org/qemu-devel/20250127120823.144949-1-ppandit@redhat.com/T/#t * This series (v4) adds more 'multifd+postcopy' qtests which test Precopy migration with 'postcopy-ram' attribute set. And run Postcopy migrations with 'multifd' channels enabled. === $ ../qtest/migration-test --tap -k -r '/x86_64/migration/multifd+postcopy' | grep -i 'slow test' # slow test /x86_64/migration/multifd+postcopy/plain executed in 1.29 secs # slow test /x86_64/migration/multifd+postcopy/recovery/tls/psk executed in 2.48 secs # slow test /x86_64/migration/multifd+postcopy/preempt/plain executed in 1.49 secs # slow test /x86_64/migration/multifd+postcopy/preempt/recovery/tls/psk executed in 2.52 secs # slow test /x86_64/migration/multifd+postcopy/tcp/tls/psk/match executed in 3.62 secs # slow test /x86_64/migration/multifd+postcopy/tcp/plain/zstd executed in 1.34 secs # slow test /x86_64/migration/multifd+postcopy/tcp/plain/cancel executed in 2.24 secs ... 66/66 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 148.41s 71 subtests passed === v3: https://lore.kernel.org/qemu-devel/20250121131032.1611245-1-ppandit@redhat.com/T/#t * This series (v3) passes all existing 'tests/qtest/migration/*' tests and adds a new one to enable multifd channels with postcopy migration. v2: https://lore.kernel.org/qemu-devel/20241129122256.96778-1-ppandit@redhat.com/T/#u * This series (v2) further refactors the 'ram_save_target_page' function to make it independent of the multifd & postcopy change. v1: https://lore.kernel.org/qemu-devel/20241126115748.118683-1-ppandit@redhat.com/T/#u * This series removes magic value (4-bytes) introduced in the previous series for the Postcopy channel. v0: https://lore.kernel.org/qemu-devel/20241029150908.1136894-1-ppandit@redhat.com/T/#u * Currently Multifd and Postcopy migration can not be used together. QEMU shows "Postcopy is not yet compatible with multifd" message. When migrating guests with large (100's GB) RAM, Multifd threads help to accelerate migration, but inability to use it with the Postcopy mode delays guest start up on the destination side. * This patch series allows to enable both Multifd and Postcopy migration together. Precopy and Multifd threads work during the initial guest (RAM) transfer. When migration moves to the Postcopy phase, Multifd threads are restrained and the Postcopy threads start to request pages from the source side. * This series introduces magic value (4-bytes) to be sent on the Postcopy channel. It helps to differentiate channels and properly setup incoming connections on the destination side. Thank you. --- Peter Xu (2): migration: Add save_postcopy_prepare() savevm handler migration/ram: Implement save_postcopy_prepare() Prasad Pandit (5): migration/multifd: move macros to multifd header migration: refactor channel discovery mechanism migration: enable multifd and postcopy together tests/qtest/migration: consolidate set capabilities tests/qtest/migration: add postcopy tests with multifd include/migration/register.h | 15 +++ migration/migration.c | 136 ++++++++++++---------- migration/multifd-nocomp.c | 3 +- migration/multifd.c | 12 +- migration/multifd.h | 5 + migration/options.c | 5 - migration/ram.c | 42 ++++++- migration/savevm.c | 33 ++++++ migration/savevm.h | 1 + tests/qtest/migration/compression-tests.c | 38 +++++- tests/qtest/migration/cpr-tests.c | 6 +- tests/qtest/migration/file-tests.c | 58 +++++---- tests/qtest/migration/framework.c | 76 ++++++++---- tests/qtest/migration/framework.h | 9 +- tests/qtest/migration/misc-tests.c | 4 +- tests/qtest/migration/postcopy-tests.c | 35 +++++- tests/qtest/migration/precopy-tests.c | 48 +++++--- tests/qtest/migration/tls-tests.c | 70 ++++++++++- 18 files changed, 437 insertions(+), 159 deletions(-) -- 2.49.0 ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v9 1/7] migration/multifd: move macros to multifd header 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 2/7] migration: refactor channel discovery mechanism Prasad Pandit ` (6 subsequent siblings) 7 siblings, 0 replies; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange, Prasad Pandit From: Prasad Pandit <pjp@fedoraproject.org> Move MULTIFD_ macros to the header file so that they are accessible from other source files. Reviewed-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- migration/multifd.c | 5 ----- migration/multifd.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) v8: no change - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/migration/multifd.c b/migration/multifd.c index dfb5189f0e..6139cabe44 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -36,11 +36,6 @@ #include "io/channel-socket.h" #include "yank_functions.h" -/* Multiple fd's */ - -#define MULTIFD_MAGIC 0x11223344U -#define MULTIFD_VERSION 1 - typedef struct { uint32_t magic; uint32_t version; diff --git a/migration/multifd.h b/migration/multifd.h index 2d337e7b3b..9b6d81e7ed 100644 --- a/migration/multifd.h +++ b/migration/multifd.h @@ -49,6 +49,11 @@ bool multifd_queue_page(RAMBlock *block, ram_addr_t offset); bool multifd_recv(void); MultiFDRecvData *multifd_get_recv_data(void); +/* Multiple fd's */ + +#define MULTIFD_MAGIC 0x11223344U +#define MULTIFD_VERSION 1 + /* Multifd Compression flags */ #define MULTIFD_FLAG_SYNC (1 << 0) -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 2/7] migration: refactor channel discovery mechanism 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 1/7] migration/multifd: move macros to multifd header Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-17 16:07 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 3/7] migration: Add save_postcopy_prepare() savevm handler Prasad Pandit ` (5 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange, Prasad Pandit From: Prasad Pandit <pjp@fedoraproject.org> The various logical migration channels don't have a standardized way of advertising themselves and their connections may be seen out of order by the migration destination. When a new connection arrives, the incoming migration currently make use of heuristics to determine which channel it belongs to. The next few patches will need to change how the multifd and postcopy capabilities interact and that affects the channel discovery heuristic. Refactor the channel discovery heuristic to make it less opaque and simplify the subsequent patches. Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- migration/migration.c | 132 +++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 61 deletions(-) v8: remove else if (!mis->from_src_file) checks and add assert(3) check - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/migration/migration.c b/migration/migration.c index d46e776e24..64f4f40ae3 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -95,6 +95,9 @@ enum mig_rp_message_type { MIG_RP_MSG_MAX }; +/* Migration channel types */ +enum { CH_MAIN, CH_MULTIFD, CH_POSTCOPY }; + /* When we add fault tolerance, we could have several migrations at once. For now we don't need to add dynamic creation of migration */ @@ -931,9 +934,8 @@ static void migration_incoming_setup(QEMUFile *f) { MigrationIncomingState *mis = migration_incoming_get_current(); - if (!mis->from_src_file) { - mis->from_src_file = f; - } + assert(!mis->from_src_file); + mis->from_src_file = f; qemu_file_set_blocking(f, false); } @@ -985,28 +987,19 @@ void migration_fd_process_incoming(QEMUFile *f) migration_incoming_process(); } -/* - * Returns true when we want to start a new incoming migration process, - * false otherwise. - */ -static bool migration_should_start_incoming(bool main_channel) +static bool migration_has_main_and_multifd_channels(void) { - /* Multifd doesn't start unless all channels are established */ - if (migrate_multifd()) { - return migration_has_all_channels(); + MigrationIncomingState *mis = migration_incoming_get_current(); + if (!mis->from_src_file) { + /* main channel not established */ + return false; } - /* Preempt channel only starts when the main channel is created */ - if (migrate_postcopy_preempt()) { - return main_channel; + if (migrate_multifd() && !multifd_recv_all_channels_created()) { + return false; } - /* - * For all the rest types of migration, we should only reach here when - * it's the main channel that's being created, and we should always - * proceed with this channel. - */ - assert(main_channel); + /* main and all multifd channels are established */ return true; } @@ -1015,59 +1008,81 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) MigrationIncomingState *mis = migration_incoming_get_current(); Error *local_err = NULL; QEMUFile *f; - bool default_channel = true; + uint8_t channel; uint32_t channel_magic = 0; int ret = 0; - if (migrate_multifd() && !migrate_mapped_ram() && - !migrate_postcopy_ram() && - qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) { - /* - * With multiple channels, it is possible that we receive channels - * out of order on destination side, causing incorrect mapping of - * source channels on destination side. Check channel MAGIC to - * decide type of channel. Please note this is best effort, postcopy - * preempt channel does not send any magic number so avoid it for - * postcopy live migration. Also tls live migration already does - * tls handshake while initializing main channel so with tls this - * issue is not possible. - */ - ret = migration_channel_read_peek(ioc, (void *)&channel_magic, - sizeof(channel_magic), errp); + if (!migration_has_main_and_multifd_channels()) { + if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) { + /* + * With multiple channels, it is possible that we receive channels + * out of order on destination side, causing incorrect mapping of + * source channels on destination side. Check channel MAGIC to + * decide type of channel. Please note this is best effort, + * postcopy preempt channel does not send any magic number so + * avoid it for postcopy live migration. Also tls live migration + * already does tls handshake while initializing main channel so + * with tls this issue is not possible. + */ + ret = migration_channel_read_peek(ioc, (void *)&channel_magic, + sizeof(channel_magic), errp); + if (ret != 0) { + return; + } - if (ret != 0) { + channel_magic = be32_to_cpu(channel_magic); + if (channel_magic == QEMU_VM_FILE_MAGIC) { + channel = CH_MAIN; + } else if (channel_magic == MULTIFD_MAGIC) { + assert(migrate_multifd()); + channel = CH_MULTIFD; + } else if (!mis->from_src_file && + mis->state == MIGRATION_STATUS_POSTCOPY_PAUSED) { + /* reconnect main channel for postcopy recovery */ + channel = CH_MAIN; + } else { + error_setg(errp, "unknown channel magic: %u", channel_magic); + return; + } + } else if (mis->from_src_file && migrate_multifd()) { + /* + * Non-peekable channels like tls/file are processed as + * multifd channels when multifd is enabled. + */ + channel = CH_MULTIFD; + } else if (!mis->from_src_file) { + channel = CH_MAIN; + } else { + error_setg(errp, "non-peekable channel used without multifd"); return; } - - default_channel = (channel_magic == cpu_to_be32(QEMU_VM_FILE_MAGIC)); } else { - default_channel = !mis->from_src_file; + assert(migrate_postcopy_preempt()); + channel = CH_POSTCOPY; } if (multifd_recv_setup(errp) != 0) { return; } - if (default_channel) { + if (channel == CH_MAIN) { f = qemu_file_new_input(ioc); migration_incoming_setup(f); - } else { + } else if (channel == CH_MULTIFD) { /* Multiple connections */ - assert(migration_needs_multiple_sockets()); - if (migrate_multifd()) { - multifd_recv_new_channel(ioc, &local_err); - } else { - assert(migrate_postcopy_preempt()); - f = qemu_file_new_input(ioc); - postcopy_preempt_new_channel(mis, f); - } + multifd_recv_new_channel(ioc, &local_err); if (local_err) { error_propagate(errp, local_err); return; } + } else if (channel == CH_POSTCOPY) { + assert(!mis->postcopy_qemufile_dst); + f = qemu_file_new_input(ioc); + postcopy_preempt_new_channel(mis, f); + return; } - if (migration_should_start_incoming(default_channel)) { + if (migration_has_main_and_multifd_channels()) { /* If it's a recovery, we're done */ if (postcopy_try_recover()) { return; @@ -1084,20 +1099,15 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) */ bool migration_has_all_channels(void) { + if (!migration_has_main_and_multifd_channels()) { + return false; + } + MigrationIncomingState *mis = migration_incoming_get_current(); - - if (!mis->from_src_file) { + if (migrate_postcopy_preempt() && !mis->postcopy_qemufile_dst) { return false; } - if (migrate_multifd()) { - return multifd_recv_all_channels_created(); - } - - if (migrate_postcopy_preempt()) { - return mis->postcopy_qemufile_dst != NULL; - } - return true; } -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 2/7] migration: refactor channel discovery mechanism 2025-04-11 11:45 ` [PATCH v9 2/7] migration: refactor channel discovery mechanism Prasad Pandit @ 2025-04-17 16:07 ` Fabiano Rosas 0 siblings, 0 replies; 29+ messages in thread From: Fabiano Rosas @ 2025-04-17 16:07 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > From: Prasad Pandit <pjp@fedoraproject.org> > > The various logical migration channels don't have a > standardized way of advertising themselves and their > connections may be seen out of order by the migration > destination. When a new connection arrives, the incoming > migration currently make use of heuristics to determine > which channel it belongs to. > > The next few patches will need to change how the multifd > and postcopy capabilities interact and that affects the > channel discovery heuristic. > > Refactor the channel discovery heuristic to make it less > opaque and simplify the subsequent patches. > > Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> Reviewed-by: Fabiano Rosas <farosas@suse.de> ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v9 3/7] migration: Add save_postcopy_prepare() savevm handler 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 1/7] migration/multifd: move macros to multifd header Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 2/7] migration: refactor channel discovery mechanism Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-17 16:07 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 4/7] migration/ram: Implement save_postcopy_prepare() Prasad Pandit ` (4 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange From: Peter Xu <peterx@redhat.com> Add a savevm handler for a module to opt-in sending extra sections right before postcopy starts, and before VM is stopped. RAM will start to use this new savevm handler in the next patch to do flush and sync for multifd pages. Note that we choose to do it before VM stopped because the current only potential user is not sensitive to VM status, so doing it before VM is stopped is preferred to enlarge any postcopy downtime. It is still a bit unfortunate that we need to introduce such a new savevm handler just for the only use case, however it's so far the cleanest. Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- include/migration/register.h | 15 +++++++++++++++ migration/migration.c | 4 ++++ migration/savevm.c | 33 +++++++++++++++++++++++++++++++++ migration/savevm.h | 1 + 4 files changed, 53 insertions(+) v8: reorder this patch before enabling multifd and postcopy together - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/include/migration/register.h b/include/migration/register.h index c041ce32f2..b79dc81b8d 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -189,6 +189,21 @@ typedef struct SaveVMHandlers { /* This runs outside the BQL! */ + /** + * @save_postcopy_prepare + * + * This hook will be invoked on the source side right before switching + * to postcopy (before VM stopped). + * + * @f: QEMUFile where to send the data + * @opaque: Data pointer passed to register_savevm_live() + * @errp: Error** used to report error message + * + * Returns: true if succeeded, false if error occured. When false is + * returned, @errp must be set. + */ + bool (*save_postcopy_prepare)(QEMUFile *f, void *opaque, Error **errp); + /** * @state_pending_estimate * diff --git a/migration/migration.c b/migration/migration.c index 64f4f40ae3..4bb29b7193 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2717,6 +2717,10 @@ static int postcopy_start(MigrationState *ms, Error **errp) } } + if (!qemu_savevm_state_postcopy_prepare(ms->to_dst_file, errp)) { + return -1; + } + trace_postcopy_start(); bql_lock(); trace_postcopy_start_set_run(); diff --git a/migration/savevm.c b/migration/savevm.c index ce158c3512..23ef4c7dc9 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1523,6 +1523,39 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f) qemu_fflush(f); } +bool qemu_savevm_state_postcopy_prepare(QEMUFile *f, Error **errp) +{ + SaveStateEntry *se; + bool ret; + + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { + if (!se->ops || !se->ops->save_postcopy_prepare) { + continue; + } + + if (se->ops->is_active) { + if (!se->ops->is_active(se->opaque)) { + continue; + } + } + + trace_savevm_section_start(se->idstr, se->section_id); + + save_section_header(f, se, QEMU_VM_SECTION_PART); + ret = se->ops->save_postcopy_prepare(f, se->opaque, errp); + save_section_footer(f, se); + + trace_savevm_section_end(se->idstr, se->section_id, ret); + + if (!ret) { + assert(*errp); + return false; + } + } + + return true; +} + int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy) { int64_t start_ts_each, end_ts_each; diff --git a/migration/savevm.h b/migration/savevm.h index 138c39a7f9..2d5e9c7166 100644 --- a/migration/savevm.h +++ b/migration/savevm.h @@ -45,6 +45,7 @@ void qemu_savevm_state_pending_exact(uint64_t *must_precopy, void qemu_savevm_state_pending_estimate(uint64_t *must_precopy, uint64_t *can_postcopy); int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy); +bool qemu_savevm_state_postcopy_prepare(QEMUFile *f, Error **errp); void qemu_savevm_send_ping(QEMUFile *f, uint32_t value); void qemu_savevm_send_open_return_path(QEMUFile *f); int qemu_savevm_send_packaged(QEMUFile *f, const uint8_t *buf, size_t len); -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 3/7] migration: Add save_postcopy_prepare() savevm handler 2025-04-11 11:45 ` [PATCH v9 3/7] migration: Add save_postcopy_prepare() savevm handler Prasad Pandit @ 2025-04-17 16:07 ` Fabiano Rosas 0 siblings, 0 replies; 29+ messages in thread From: Fabiano Rosas @ 2025-04-17 16:07 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange Prasad Pandit <ppandit@redhat.com> writes: > From: Peter Xu <peterx@redhat.com> > > Add a savevm handler for a module to opt-in sending extra sections right > before postcopy starts, and before VM is stopped. > > RAM will start to use this new savevm handler in the next patch to do flush > and sync for multifd pages. > > Note that we choose to do it before VM stopped because the current only > potential user is not sensitive to VM status, so doing it before VM is > stopped is preferred to enlarge any postcopy downtime. > > It is still a bit unfortunate that we need to introduce such a new savevm > handler just for the only use case, however it's so far the cleanest. > > Signed-off-by: Peter Xu <peterx@redhat.com> > Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> Reviewed-by: Fabiano Rosas <farosas@suse.de> ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v9 4/7] migration/ram: Implement save_postcopy_prepare() 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit ` (2 preceding siblings ...) 2025-04-11 11:45 ` [PATCH v9 3/7] migration: Add save_postcopy_prepare() savevm handler Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-17 16:08 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 5/7] migration: enable multifd and postcopy together Prasad Pandit ` (3 subsequent siblings) 7 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange From: Peter Xu <peterx@redhat.com> Implement save_postcopy_prepare(), preparing for the enablement of both multifd and postcopy. Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- migration/ram.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) v8: reorder patch and some typographical corrections. - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/migration/ram.c b/migration/ram.c index 424df6d9f1..753042456e 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -4420,6 +4420,42 @@ static int ram_resume_prepare(MigrationState *s, void *opaque) return 0; } +static bool ram_save_postcopy_prepare(QEMUFile *f, void *opaque, Error **errp) +{ + int ret; + + if (migrate_multifd()) { + /* + * When multifd is enabled, source QEMU needs to make sure all the + * pages queued before postcopy starts have been flushed. + * + * The load of these pages must happen before switching to postcopy. + * It's because loading of guest pages (so far) in multifd recv + * threads is still non-atomic, so the load cannot happen with vCPUs + * running on the destination side. + * + * This flush and sync will guarantee that those pages are loaded + * _before_ postcopy starts on the destination. The rationale is, + * this happens before VM stops (and before source QEMU sends all + * the rest of the postcopy messages). So when the destination QEMU + * receives the postcopy messages, it must have received the sync + * message on the main channel (either RAM_SAVE_FLAG_MULTIFD_FLUSH, + * or RAM_SAVE_FLAG_EOS), and such message would guarantee that + * all previous guest pages queued in the multifd channels are + * completely loaded. + */ + ret = multifd_ram_flush_and_sync(f); + if (ret < 0) { + error_setg(errp, "%s: multifd flush and sync failed", __func__); + return false; + } + } + + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + + return true; +} + void postcopy_preempt_shutdown_file(MigrationState *s) { qemu_put_be64(s->postcopy_qemufile_src, RAM_SAVE_FLAG_EOS); @@ -4439,6 +4475,7 @@ static SaveVMHandlers savevm_ram_handlers = { .load_setup = ram_load_setup, .load_cleanup = ram_load_cleanup, .resume_prepare = ram_resume_prepare, + .save_postcopy_prepare = ram_save_postcopy_prepare, }; static void ram_mig_ram_block_resized(RAMBlockNotifier *n, void *host, -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 4/7] migration/ram: Implement save_postcopy_prepare() 2025-04-11 11:45 ` [PATCH v9 4/7] migration/ram: Implement save_postcopy_prepare() Prasad Pandit @ 2025-04-17 16:08 ` Fabiano Rosas 0 siblings, 0 replies; 29+ messages in thread From: Fabiano Rosas @ 2025-04-17 16:08 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange Prasad Pandit <ppandit@redhat.com> writes: > From: Peter Xu <peterx@redhat.com> > > Implement save_postcopy_prepare(), preparing for the enablement > of both multifd and postcopy. > > Signed-off-by: Peter Xu <peterx@redhat.com> > Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> Reviewed-by: Fabiano Rosas <farosas@suse.de> ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v9 5/7] migration: enable multifd and postcopy together 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit ` (3 preceding siblings ...) 2025-04-11 11:45 ` [PATCH v9 4/7] migration/ram: Implement save_postcopy_prepare() Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 6/7] tests/qtest/migration: consolidate set capabilities Prasad Pandit ` (2 subsequent siblings) 7 siblings, 0 replies; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange, Prasad Pandit From: Prasad Pandit <pjp@fedoraproject.org> Enable Multifd and Postcopy migration together. The migration_ioc_process_incoming() routine checks magic value sent on each channel and helps to properly setup multifd and postcopy channels. The Precopy and Multifd threads work during the initial guest RAM transfer. When migration moves to the Postcopy phase, the multifd threads cease to send data on multifd channels and Postcopy threads on the destination request/pull data from the source side. Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- migration/multifd-nocomp.c | 3 ++- migration/multifd.c | 7 +++++++ migration/options.c | 5 ----- migration/ram.c | 5 ++--- 4 files changed, 11 insertions(+), 9 deletions(-) v8: remove a !migration_in_postcopy() check - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/migration/multifd-nocomp.c b/migration/multifd-nocomp.c index ffe75256c9..02f8bf8ce8 100644 --- a/migration/multifd-nocomp.c +++ b/migration/multifd-nocomp.c @@ -17,6 +17,7 @@ #include "migration-stats.h" #include "multifd.h" #include "options.h" +#include "migration.h" #include "qapi/error.h" #include "qemu/cutils.h" #include "qemu/error-report.h" @@ -399,7 +400,7 @@ int multifd_ram_flush_and_sync(QEMUFile *f) MultiFDSyncReq req; int ret; - if (!migrate_multifd()) { + if (!migrate_multifd() || migration_in_postcopy()) { return 0; } diff --git a/migration/multifd.c b/migration/multifd.c index 6139cabe44..074d16d07d 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -1379,6 +1379,13 @@ static void *multifd_recv_thread(void *opaque) } if (has_data) { + /* + * multifd thread should not be active and receive data + * when migration is in the Postcopy phase. Two threads + * writing the same memory area could easily corrupt + * the guest state. + */ + assert(!migration_in_postcopy()); if (is_device_state) { assert(use_packets); ret = multifd_device_state_recv(p, &local_err); diff --git a/migration/options.c b/migration/options.c index b0ac2ea408..48aa6076de 100644 --- a/migration/options.c +++ b/migration/options.c @@ -491,11 +491,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) error_setg(errp, "Postcopy is not compatible with ignore-shared"); return false; } - - if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { - error_setg(errp, "Postcopy is not yet compatible with multifd"); - return false; - } } if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { diff --git a/migration/ram.c b/migration/ram.c index 753042456e..533c64b941 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1976,9 +1976,8 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss) } } - if (migrate_multifd()) { - RAMBlock *block = pss->block; - return ram_save_multifd_page(block, offset); + if (migrate_multifd() && !migration_in_postcopy()) { + return ram_save_multifd_page(pss->block, offset); } return ram_save_page(rs, pss); -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 6/7] tests/qtest/migration: consolidate set capabilities 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit ` (4 preceding siblings ...) 2025-04-11 11:45 ` [PATCH v9 5/7] migration: enable multifd and postcopy together Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-17 16:11 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 7/7] tests/qtest/migration: add postcopy tests with multifd Prasad Pandit 2025-04-16 0:31 ` [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Fabiano Rosas 7 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange, Prasad Pandit From: Prasad Pandit <pjp@fedoraproject.org> Migration capabilities are set in multiple '.start_hook' functions for various tests. Instead, consolidate setting capabilities in 'migrate_start_set_capabilities()' function which is called from the 'migrate_start()' function. While simplifying the capabilities setting, it helps to declutter the qtest sources. Suggested-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- tests/qtest/migration/compression-tests.c | 22 +++++-- tests/qtest/migration/cpr-tests.c | 6 +- tests/qtest/migration/file-tests.c | 58 ++++++++--------- tests/qtest/migration/framework.c | 76 ++++++++++++++++------- tests/qtest/migration/framework.h | 9 ++- tests/qtest/migration/misc-tests.c | 4 +- tests/qtest/migration/postcopy-tests.c | 8 ++- tests/qtest/migration/precopy-tests.c | 29 +++++---- tests/qtest/migration/tls-tests.c | 23 ++++++- 9 files changed, 151 insertions(+), 84 deletions(-) v8: no change - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/tests/qtest/migration/compression-tests.c b/tests/qtest/migration/compression-tests.c index 8b58401b84..41e79f031b 100644 --- a/tests/qtest/migration/compression-tests.c +++ b/tests/qtest/migration/compression-tests.c @@ -35,6 +35,9 @@ static void test_multifd_tcp_zstd(void) { MigrateCommon args = { .listen_uri = "defer", + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, .start_hook = migrate_hook_start_precopy_tcp_multifd_zstd, }; test_precopy_common(&args); @@ -56,6 +59,9 @@ static void test_multifd_tcp_qatzip(void) { MigrateCommon args = { .listen_uri = "defer", + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, .start_hook = migrate_hook_start_precopy_tcp_multifd_qatzip, }; test_precopy_common(&args); @@ -74,6 +80,9 @@ static void test_multifd_tcp_qpl(void) { MigrateCommon args = { .listen_uri = "defer", + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, .start_hook = migrate_hook_start_precopy_tcp_multifd_qpl, }; test_precopy_common(&args); @@ -92,6 +101,9 @@ static void test_multifd_tcp_uadk(void) { MigrateCommon args = { .listen_uri = "defer", + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, .start_hook = migrate_hook_start_precopy_tcp_multifd_uadk, }; test_precopy_common(&args); @@ -103,10 +115,6 @@ migrate_hook_start_xbzrle(QTestState *from, QTestState *to) { migrate_set_parameter_int(from, "xbzrle-cache-size", 33554432); - - migrate_set_capability(from, "xbzrle", true); - migrate_set_capability(to, "xbzrle", true); - return NULL; } @@ -118,6 +126,9 @@ static void test_precopy_unix_xbzrle(void) .listen_uri = uri, .start_hook = migrate_hook_start_xbzrle, .iterations = 2, + .start = { + .caps[MIGRATION_CAPABILITY_XBZRLE] = true, + }, /* * XBZRLE needs pages to be modified when doing the 2nd+ round * iteration to have real data pushed to the stream. @@ -146,6 +157,9 @@ static void test_multifd_tcp_zlib(void) { MigrateCommon args = { .listen_uri = "defer", + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, .start_hook = migrate_hook_start_precopy_tcp_multifd_zlib, }; test_precopy_common(&args); diff --git a/tests/qtest/migration/cpr-tests.c b/tests/qtest/migration/cpr-tests.c index 4758841824..5536e14610 100644 --- a/tests/qtest/migration/cpr-tests.c +++ b/tests/qtest/migration/cpr-tests.c @@ -24,9 +24,6 @@ static void *migrate_hook_start_mode_reboot(QTestState *from, QTestState *to) migrate_set_parameter_str(from, "mode", "cpr-reboot"); migrate_set_parameter_str(to, "mode", "cpr-reboot"); - migrate_set_capability(from, "x-ignore-shared", true); - migrate_set_capability(to, "x-ignore-shared", true); - return NULL; } @@ -39,6 +36,9 @@ static void test_mode_reboot(void) .connect_uri = uri, .listen_uri = "defer", .start_hook = migrate_hook_start_mode_reboot, + .start = { + .caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED] = true, + }, }; test_file_common(&args, true); diff --git a/tests/qtest/migration/file-tests.c b/tests/qtest/migration/file-tests.c index f260e2871d..4d78ce0855 100644 --- a/tests/qtest/migration/file-tests.c +++ b/tests/qtest/migration/file-tests.c @@ -107,15 +107,6 @@ static void test_precopy_file_offset_bad(void) test_file_common(&args, false); } -static void *migrate_hook_start_mapped_ram(QTestState *from, - QTestState *to) -{ - migrate_set_capability(from, "mapped-ram", true); - migrate_set_capability(to, "mapped-ram", true); - - return NULL; -} - static void test_precopy_file_mapped_ram_live(void) { g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs, @@ -123,7 +114,9 @@ static void test_precopy_file_mapped_ram_live(void) MigrateCommon args = { .connect_uri = uri, .listen_uri = "defer", - .start_hook = migrate_hook_start_mapped_ram, + .start = { + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + }, }; test_file_common(&args, false); @@ -136,26 +129,14 @@ static void test_precopy_file_mapped_ram(void) MigrateCommon args = { .connect_uri = uri, .listen_uri = "defer", - .start_hook = migrate_hook_start_mapped_ram, + .start = { + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + }, }; test_file_common(&args, true); } -static void *migrate_hook_start_multifd_mapped_ram(QTestState *from, - QTestState *to) -{ - migrate_hook_start_mapped_ram(from, to); - - migrate_set_parameter_int(from, "multifd-channels", 4); - migrate_set_parameter_int(to, "multifd-channels", 4); - - migrate_set_capability(from, "multifd", true); - migrate_set_capability(to, "multifd", true); - - return NULL; -} - static void test_multifd_file_mapped_ram_live(void) { g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs, @@ -163,7 +144,10 @@ static void test_multifd_file_mapped_ram_live(void) MigrateCommon args = { .connect_uri = uri, .listen_uri = "defer", - .start_hook = migrate_hook_start_multifd_mapped_ram, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + }, }; test_file_common(&args, false); @@ -176,7 +160,10 @@ static void test_multifd_file_mapped_ram(void) MigrateCommon args = { .connect_uri = uri, .listen_uri = "defer", - .start_hook = migrate_hook_start_multifd_mapped_ram, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + }, }; test_file_common(&args, true); @@ -185,8 +172,6 @@ static void test_multifd_file_mapped_ram(void) static void *migrate_hook_start_multifd_mapped_ram_dio(QTestState *from, QTestState *to) { - migrate_hook_start_multifd_mapped_ram(from, to); - migrate_set_parameter_bool(from, "direct-io", true); migrate_set_parameter_bool(to, "direct-io", true); @@ -201,6 +186,10 @@ static void test_multifd_file_mapped_ram_dio(void) .connect_uri = uri, .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_mapped_ram_dio, + .start = { + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; if (!probe_o_direct_support(tmpfs)) { @@ -246,7 +235,6 @@ static void *migrate_hook_start_multifd_mapped_ram_fdset_dio(QTestState *from, fdset_add_fds(from, file, O_WRONLY, 2, true); fdset_add_fds(to, file, O_RDONLY, 2, true); - migrate_hook_start_multifd_mapped_ram(from, to); migrate_set_parameter_bool(from, "direct-io", true); migrate_set_parameter_bool(to, "direct-io", true); @@ -261,8 +249,6 @@ static void *migrate_hook_start_multifd_mapped_ram_fdset(QTestState *from, fdset_add_fds(from, file, O_WRONLY, 2, false); fdset_add_fds(to, file, O_RDONLY, 2, false); - migrate_hook_start_multifd_mapped_ram(from, to); - return NULL; } @@ -275,6 +261,10 @@ static void test_multifd_file_mapped_ram_fdset(void) .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_mapped_ram_fdset, .end_hook = migrate_hook_end_multifd_mapped_ram_fdset, + .start = { + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; test_file_common(&args, true); @@ -289,6 +279,10 @@ static void test_multifd_file_mapped_ram_fdset_dio(void) .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_mapped_ram_fdset_dio, .end_hook = migrate_hook_end_multifd_mapped_ram_fdset, + .start = { + .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true, + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; if (!probe_o_direct_support(tmpfs)) { diff --git a/tests/qtest/migration/framework.c b/tests/qtest/migration/framework.c index 10e1d04b58..be6c245843 100644 --- a/tests/qtest/migration/framework.c +++ b/tests/qtest/migration/framework.c @@ -30,6 +30,7 @@ #define QEMU_VM_FILE_MAGIC 0x5145564d #define QEMU_ENV_SRC "QTEST_QEMU_BINARY_SRC" #define QEMU_ENV_DST "QTEST_QEMU_BINARY_DST" +#define MULTIFD_TEST_CHANNELS 4 unsigned start_address; unsigned end_address; @@ -207,6 +208,52 @@ static QList *migrate_start_get_qmp_capabilities(const MigrateStart *args) return capabilities; } +static void migrate_start_set_capabilities(QTestState *from, QTestState *to, + MigrateStart *args) +{ + /* + * MigrationCapability_lookup and MIGRATION_CAPABILITY_ constants + * are from qapi-types-migration.h. + */ + for (uint8_t i = 0; i < MIGRATION_CAPABILITY__MAX; i++) + { + if (!args->caps[i]) { + continue; + } + if (from) { + migrate_set_capability(from, + MigrationCapability_lookup.array[i], true); + } + if (to) { + migrate_set_capability(to, + MigrationCapability_lookup.array[i], true); + } + } + + /* + * Always enable migration events. Libvirt always uses it, let's try + * to mimic as closer as that. + */ + migrate_set_capability(from, "events", true); + if (!args->defer_target_connect) { + migrate_set_capability(to, "events", true); + } + + /* + * Default number of channels should be fine for most + * tests. Individual tests can override by calling + * migrate_set_parameter() directly. + */ + if (args->caps[MIGRATION_CAPABILITY_MULTIFD]) { + migrate_set_parameter_int(from, "multifd-channels", + MULTIFD_TEST_CHANNELS); + migrate_set_parameter_int(to, "multifd-channels", + MULTIFD_TEST_CHANNELS); + } + + return; +} + int migrate_start(QTestState **from, QTestState **to, const char *uri, MigrateStart *args) { @@ -379,14 +426,7 @@ int migrate_start(QTestState **from, QTestState **to, const char *uri, unlink(shmem_path); } - /* - * Always enable migration events. Libvirt always uses it, let's try - * to mimic as closer as that. - */ - migrate_set_capability(*from, "events", true); - if (!args->defer_target_connect) { - migrate_set_capability(*to, "events", true); - } + migrate_start_set_capabilities(*from, *to, args); return 0; } @@ -432,6 +472,10 @@ static int migrate_postcopy_prepare(QTestState **from_ptr, { QTestState *from, *to; + /* set postcopy capabilities */ + args->start.caps[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME] = true; + args->start.caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] = true; + if (migrate_start(&from, &to, "defer", &args->start)) { return -1; } @@ -440,17 +484,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr, args->postcopy_data = args->start_hook(from, to); } - migrate_set_capability(from, "postcopy-ram", true); - migrate_set_capability(to, "postcopy-ram", true); - migrate_set_capability(to, "postcopy-blocktime", true); - - if (args->postcopy_preempt) { - migrate_set_capability(from, "postcopy-preempt", true); - migrate_set_capability(to, "postcopy-preempt", true); - } - migrate_ensure_non_converge(from); - migrate_prepare_for_dirty_mem(from); qtest_qmp_assert_success(to, "{ 'execute': 'migrate-incoming'," " 'arguments': { " @@ -948,15 +982,9 @@ void *migrate_hook_start_precopy_tcp_multifd_common(QTestState *from, QTestState *to, const char *method) { - migrate_set_parameter_int(from, "multifd-channels", 16); - migrate_set_parameter_int(to, "multifd-channels", 16); - migrate_set_parameter_str(from, "multifd-compression", method); migrate_set_parameter_str(to, "multifd-compression", method); - migrate_set_capability(from, "multifd", true); - migrate_set_capability(to, "multifd", true); - /* Start incoming migration from the 1st socket */ migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}"); diff --git a/tests/qtest/migration/framework.h b/tests/qtest/migration/framework.h index e4a11870f6..01e425e64e 100644 --- a/tests/qtest/migration/framework.h +++ b/tests/qtest/migration/framework.h @@ -12,6 +12,7 @@ #define TEST_FRAMEWORK_H #include "libqtest.h" +#include <qapi/qapi-types-migration.h> #define FILE_TEST_FILENAME "migfile" #define FILE_TEST_OFFSET 0x1000 @@ -120,6 +121,13 @@ typedef struct { /* Do not connect to target monitor and qtest sockets in qtest_init */ bool defer_target_connect; + + /* + * Migration capabilities to be set in both source and + * destination. For unilateral capabilities, use + * migration_set_capabilities(). + */ + bool caps[MIGRATION_CAPABILITY__MAX]; } MigrateStart; typedef enum PostcopyRecoveryFailStage { @@ -207,7 +215,6 @@ typedef struct { /* Postcopy specific fields */ void *postcopy_data; - bool postcopy_preempt; PostcopyRecoveryFailStage postcopy_recovery_fail_stage; } MigrateCommon; diff --git a/tests/qtest/migration/misc-tests.c b/tests/qtest/migration/misc-tests.c index 2e612d9e38..54995256d8 100644 --- a/tests/qtest/migration/misc-tests.c +++ b/tests/qtest/migration/misc-tests.c @@ -98,6 +98,7 @@ static void test_ignore_shared(void) QTestState *from, *to; MigrateStart args = { .use_shmem = true, + .caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED] = true, }; if (migrate_start(&from, &to, uri, &args)) { @@ -107,9 +108,6 @@ static void test_ignore_shared(void) migrate_ensure_non_converge(from); migrate_prepare_for_dirty_mem(from); - migrate_set_capability(from, "x-ignore-shared", true); - migrate_set_capability(to, "x-ignore-shared", true); - /* Wait for the first serial output from the source */ wait_for_serial("src_serial"); diff --git a/tests/qtest/migration/postcopy-tests.c b/tests/qtest/migration/postcopy-tests.c index 982457bed1..483e3ff99f 100644 --- a/tests/qtest/migration/postcopy-tests.c +++ b/tests/qtest/migration/postcopy-tests.c @@ -39,7 +39,9 @@ static void test_postcopy_suspend(void) static void test_postcopy_preempt(void) { MigrateCommon args = { - .postcopy_preempt = true, + .start = { + .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true, + }, }; test_postcopy_common(&args); @@ -73,7 +75,9 @@ static void test_postcopy_recovery_fail_reconnect(void) static void test_postcopy_preempt_recovery(void) { MigrateCommon args = { - .postcopy_preempt = true, + .start = { + .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true, + }, }; test_postcopy_recovery_common(&args); diff --git a/tests/qtest/migration/precopy-tests.c b/tests/qtest/migration/precopy-tests.c index ba273d10b9..f8404793b8 100644 --- a/tests/qtest/migration/precopy-tests.c +++ b/tests/qtest/migration/precopy-tests.c @@ -108,23 +108,14 @@ static void test_precopy_tcp_plain(void) test_precopy_common(&args); } -static void *migrate_hook_start_switchover_ack(QTestState *from, QTestState *to) -{ - - migrate_set_capability(from, "return-path", true); - migrate_set_capability(to, "return-path", true); - - migrate_set_capability(from, "switchover-ack", true); - migrate_set_capability(to, "switchover-ack", true); - - return NULL; -} - static void test_precopy_tcp_switchover_ack(void) { MigrateCommon args = { .listen_uri = "tcp:127.0.0.1:0", - .start_hook = migrate_hook_start_switchover_ack, + .start = { + .caps[MIGRATION_CAPABILITY_RETURN_PATH] = true, + .caps[MIGRATION_CAPABILITY_SWITCHOVER_ACK] = true, + }, /* * Source VM must be running in order to consider the switchover ACK * when deciding to do switchover or not. @@ -393,6 +384,9 @@ static void test_multifd_tcp_uri_none(void) MigrateCommon args = { .listen_uri = "defer", .start_hook = migrate_hook_start_precopy_tcp_multifd, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, /* * Multifd is more complicated than most of the features, it * directly takes guest page buffers when sending, make sure @@ -408,6 +402,9 @@ static void test_multifd_tcp_zero_page_legacy(void) MigrateCommon args = { .listen_uri = "defer", .start_hook = migrate_hook_start_precopy_tcp_multifd_zero_page_legacy, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, /* * Multifd is more complicated than most of the features, it * directly takes guest page buffers when sending, make sure @@ -423,6 +420,9 @@ static void test_multifd_tcp_no_zero_page(void) MigrateCommon args = { .listen_uri = "defer", .start_hook = migrate_hook_start_precopy_tcp_multifd_no_zero_page, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, /* * Multifd is more complicated than most of the features, it * directly takes guest page buffers when sending, make sure @@ -439,6 +439,9 @@ static void test_multifd_tcp_channels_none(void) .listen_uri = "defer", .start_hook = migrate_hook_start_precopy_tcp_multifd, .live = true, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, .connect_channels = ("[ { 'channel-type': 'main'," " 'addr': { 'transport': 'socket'," " 'type': 'inet'," diff --git a/tests/qtest/migration/tls-tests.c b/tests/qtest/migration/tls-tests.c index 2cb4a44bcd..72f44defbb 100644 --- a/tests/qtest/migration/tls-tests.c +++ b/tests/qtest/migration/tls-tests.c @@ -375,9 +375,11 @@ static void test_postcopy_tls_psk(void) static void test_postcopy_preempt_tls_psk(void) { MigrateCommon args = { - .postcopy_preempt = true, .start_hook = migrate_hook_start_tls_psk_match, .end_hook = migrate_hook_end_tls_psk, + .start = { + .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true, + }, }; test_postcopy_common(&args); @@ -397,9 +399,11 @@ static void test_postcopy_recovery_tls_psk(void) static void test_postcopy_preempt_all(void) { MigrateCommon args = { - .postcopy_preempt = true, .start_hook = migrate_hook_start_tls_psk_match, .end_hook = migrate_hook_end_tls_psk, + .start = { + .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true, + }, }; test_postcopy_recovery_common(&args); @@ -631,6 +635,9 @@ static void test_multifd_tcp_tls_psk_match(void) .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tcp_tls_psk_match, .end_hook = migrate_hook_end_tls_psk, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; test_precopy_common(&args); } @@ -640,6 +647,7 @@ static void test_multifd_tcp_tls_psk_mismatch(void) MigrateCommon args = { .start = { .hide_stderr = true, + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, }, .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tcp_tls_psk_mismatch, @@ -656,6 +664,9 @@ static void test_multifd_tcp_tls_x509_default_host(void) .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tls_x509_default_host, .end_hook = migrate_hook_end_tls_x509, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; test_precopy_common(&args); } @@ -666,6 +677,9 @@ static void test_multifd_tcp_tls_x509_override_host(void) .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tls_x509_override_host, .end_hook = migrate_hook_end_tls_x509, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; test_precopy_common(&args); } @@ -688,6 +702,7 @@ static void test_multifd_tcp_tls_x509_mismatch_host(void) MigrateCommon args = { .start = { .hide_stderr = true, + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, }, .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tls_x509_mismatch_host, @@ -703,6 +718,9 @@ static void test_multifd_tcp_tls_x509_allow_anon_client(void) .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tls_x509_allow_anon_client, .end_hook = migrate_hook_end_tls_x509, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, }; test_precopy_common(&args); } @@ -712,6 +730,7 @@ static void test_multifd_tcp_tls_x509_reject_anon_client(void) MigrateCommon args = { .start = { .hide_stderr = true, + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, }, .listen_uri = "defer", .start_hook = migrate_hook_start_multifd_tls_x509_reject_anon_client, -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 6/7] tests/qtest/migration: consolidate set capabilities 2025-04-11 11:45 ` [PATCH v9 6/7] tests/qtest/migration: consolidate set capabilities Prasad Pandit @ 2025-04-17 16:11 ` Fabiano Rosas 0 siblings, 0 replies; 29+ messages in thread From: Fabiano Rosas @ 2025-04-17 16:11 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > From: Prasad Pandit <pjp@fedoraproject.org> > > Migration capabilities are set in multiple '.start_hook' > functions for various tests. Instead, consolidate setting > capabilities in 'migrate_start_set_capabilities()' function > which is called from the 'migrate_start()' function. > While simplifying the capabilities setting, it helps > to declutter the qtest sources. > > Suggested-by: Fabiano Rosas <farosas@suse.de> > Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> Reviewed-by: Fabiano Rosas <farosas@suse.de> ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v9 7/7] tests/qtest/migration: add postcopy tests with multifd 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit ` (5 preceding siblings ...) 2025-04-11 11:45 ` [PATCH v9 6/7] tests/qtest/migration: consolidate set capabilities Prasad Pandit @ 2025-04-11 11:45 ` Prasad Pandit 2025-04-17 16:10 ` Fabiano Rosas 2025-04-16 0:31 ` [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Fabiano Rosas 7 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-11 11:45 UTC (permalink / raw) To: qemu-devel; +Cc: farosas, peterx, berrange, Prasad Pandit From: Prasad Pandit <pjp@fedoraproject.org> Add new qtests to run postcopy migration with multifd channels enabled. Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> --- tests/qtest/migration/compression-tests.c | 16 ++++++++ tests/qtest/migration/postcopy-tests.c | 27 +++++++++++++ tests/qtest/migration/precopy-tests.c | 19 +++++++++ tests/qtest/migration/tls-tests.c | 47 +++++++++++++++++++++++ 4 files changed, 109 insertions(+) v8: no change - https://lore.kernel.org/qemu-devel/20250318123846.1370312-1-ppandit@redhat.com/T/#t diff --git a/tests/qtest/migration/compression-tests.c b/tests/qtest/migration/compression-tests.c index 41e79f031b..a788a8d4a7 100644 --- a/tests/qtest/migration/compression-tests.c +++ b/tests/qtest/migration/compression-tests.c @@ -42,6 +42,20 @@ static void test_multifd_tcp_zstd(void) }; test_precopy_common(&args); } + +static void test_multifd_postcopy_tcp_zstd(void) +{ + MigrateCommon args = { + .listen_uri = "defer", + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + .caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] = true, + }, + .start_hook = migrate_hook_start_precopy_tcp_multifd_zstd, + }; + + test_precopy_common(&args); +} #endif /* CONFIG_ZSTD */ #ifdef CONFIG_QATZIP @@ -184,6 +198,8 @@ void migration_test_add_compression(MigrationTestEnv *env) #ifdef CONFIG_ZSTD migration_test_add("/migration/multifd/tcp/plain/zstd", test_multifd_tcp_zstd); + migration_test_add("/migration/multifd+postcopy/tcp/plain/zstd", + test_multifd_postcopy_tcp_zstd); #endif #ifdef CONFIG_QATZIP diff --git a/tests/qtest/migration/postcopy-tests.c b/tests/qtest/migration/postcopy-tests.c index 483e3ff99f..eb637f94f7 100644 --- a/tests/qtest/migration/postcopy-tests.c +++ b/tests/qtest/migration/postcopy-tests.c @@ -94,6 +94,29 @@ static void migration_test_add_postcopy_smoke(MigrationTestEnv *env) } } +static void test_multifd_postcopy(void) +{ + MigrateCommon args = { + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, + }; + + test_postcopy_common(&args); +} + +static void test_multifd_postcopy_preempt(void) +{ + MigrateCommon args = { + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + .caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT] = true, + }, + }; + + test_postcopy_common(&args); +} + void migration_test_add_postcopy(MigrationTestEnv *env) { migration_test_add_postcopy_smoke(env); @@ -114,6 +137,10 @@ void migration_test_add_postcopy(MigrationTestEnv *env) "/migration/postcopy/recovery/double-failures/reconnect", test_postcopy_recovery_fail_reconnect); + migration_test_add("/migration/postcopy/multifd/plain", + test_multifd_postcopy); + migration_test_add("/migration/postcopy/multifd/preempt/plain", + test_multifd_postcopy_preempt); if (env->is_x86) { migration_test_add("/migration/postcopy/suspend", test_postcopy_suspend); diff --git a/tests/qtest/migration/precopy-tests.c b/tests/qtest/migration/precopy-tests.c index f8404793b8..b2b0db8076 100644 --- a/tests/qtest/migration/precopy-tests.c +++ b/tests/qtest/migration/precopy-tests.c @@ -34,6 +34,7 @@ #define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */ static char *tmpfs; +static bool postcopy_ram = false; static void test_precopy_unix_plain(void) { @@ -476,6 +477,11 @@ static void test_multifd_tcp_cancel(void) migrate_ensure_non_converge(from); migrate_prepare_for_dirty_mem(from); + if (postcopy_ram) { + migrate_set_capability(from, "postcopy-ram", true); + migrate_set_capability(to, "postcopy-ram", true); + } + migrate_set_parameter_int(from, "multifd-channels", 16); migrate_set_parameter_int(to, "multifd-channels", 16); @@ -517,6 +523,10 @@ static void test_multifd_tcp_cancel(void) return; } + if (postcopy_ram) { + migrate_set_capability(to2, "postcopy-ram", true); + } + migrate_set_parameter_int(to2, "multifd-channels", 16); migrate_set_capability(to2, "multifd", true); @@ -540,6 +550,13 @@ static void test_multifd_tcp_cancel(void) migrate_end(from, to2, true); } +static void test_multifd_postcopy_tcp_cancel(void) +{ + postcopy_ram = true; + test_multifd_tcp_cancel(); + postcopy_ram = false; +} + static void test_cancel_src_after_failed(QTestState *from, QTestState *to, const char *uri, const char *phase) { @@ -1127,6 +1144,8 @@ static void migration_test_add_precopy_smoke(MigrationTestEnv *env) test_multifd_tcp_uri_none); migration_test_add("/migration/multifd/tcp/plain/cancel", test_multifd_tcp_cancel); + migration_test_add("/migration/multifd+postcopy/tcp/plain/cancel", + test_multifd_postcopy_tcp_cancel); } void migration_test_add_precopy(MigrationTestEnv *env) diff --git a/tests/qtest/migration/tls-tests.c b/tests/qtest/migration/tls-tests.c index 72f44defbb..54581e182f 100644 --- a/tests/qtest/migration/tls-tests.c +++ b/tests/qtest/migration/tls-tests.c @@ -395,6 +395,19 @@ static void test_postcopy_recovery_tls_psk(void) test_postcopy_recovery_common(&args); } +static void test_multifd_postcopy_recovery_tls_psk(void) +{ + MigrateCommon args = { + .start_hook = migrate_hook_start_tls_psk_match, + .end_hook = migrate_hook_end_tls_psk, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, + }; + + test_postcopy_recovery_common(&args); +} + /* This contains preempt+recovery+tls test altogether */ static void test_postcopy_preempt_all(void) { @@ -409,6 +422,19 @@ static void test_postcopy_preempt_all(void) test_postcopy_recovery_common(&args); } +static void test_multifd_postcopy_preempt_recovery_tls_psk(void) +{ + MigrateCommon args = { + .start_hook = migrate_hook_start_tls_psk_match, + .end_hook = migrate_hook_end_tls_psk, + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + }, + }; + + test_postcopy_recovery_common(&args); +} + static void test_precopy_unix_tls_psk(void) { g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); @@ -657,6 +683,21 @@ static void test_multifd_tcp_tls_psk_mismatch(void) test_precopy_common(&args); } +static void test_multifd_postcopy_tcp_tls_psk_match(void) +{ + MigrateCommon args = { + .start = { + .caps[MIGRATION_CAPABILITY_MULTIFD] = true, + .caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] = true, + }, + .listen_uri = "defer", + .start_hook = migrate_hook_start_multifd_tcp_tls_psk_match, + .end_hook = migrate_hook_end_tls_psk, + }; + + test_precopy_common(&args); +} + #ifdef CONFIG_TASN1 static void test_multifd_tcp_tls_x509_default_host(void) { @@ -774,6 +815,10 @@ void migration_test_add_tls(MigrationTestEnv *env) test_postcopy_preempt_tls_psk); migration_test_add("/migration/postcopy/preempt/recovery/tls/psk", test_postcopy_preempt_all); + migration_test_add("/migration/postcopy/multifd/recovery/tls/psk", + test_multifd_postcopy_recovery_tls_psk); + migration_test_add("/migration/postcopy/multifd/preempt/recovery/tls/psk", + test_multifd_postcopy_preempt_recovery_tls_psk); } #ifdef CONFIG_TASN1 migration_test_add("/migration/precopy/unix/tls/x509/default-host", @@ -805,6 +850,8 @@ void migration_test_add_tls(MigrationTestEnv *env) test_multifd_tcp_tls_psk_match); migration_test_add("/migration/multifd/tcp/tls/psk/mismatch", test_multifd_tcp_tls_psk_mismatch); + migration_test_add("/migration/multifd+postcopy/tcp/tls/psk/match", + test_multifd_postcopy_tcp_tls_psk_match); #ifdef CONFIG_TASN1 migration_test_add("/migration/multifd/tcp/tls/x509/default-host", test_multifd_tcp_tls_x509_default_host); -- 2.49.0 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 7/7] tests/qtest/migration: add postcopy tests with multifd 2025-04-11 11:45 ` [PATCH v9 7/7] tests/qtest/migration: add postcopy tests with multifd Prasad Pandit @ 2025-04-17 16:10 ` Fabiano Rosas 0 siblings, 0 replies; 29+ messages in thread From: Fabiano Rosas @ 2025-04-17 16:10 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > From: Prasad Pandit <pjp@fedoraproject.org> > > Add new qtests to run postcopy migration with multifd > channels enabled. > > Signed-off-by: Prasad Pandit <pjp@fedoraproject.org> Reviewed-by: Fabiano Rosas <farosas@suse.de> ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit ` (6 preceding siblings ...) 2025-04-11 11:45 ` [PATCH v9 7/7] tests/qtest/migration: add postcopy tests with multifd Prasad Pandit @ 2025-04-16 0:31 ` Fabiano Rosas 2025-04-16 12:59 ` Fabiano Rosas 7 siblings, 1 reply; 29+ messages in thread From: Fabiano Rosas @ 2025-04-16 0:31 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > From: Prasad Pandit <pjp@fedoraproject.org> > > Hello, > > > * This series (v9) does minor refactoring and reordering changes as > suggested in the review of earlier series (v8). Also tried to > reproduce/debug a qtest hang issue, but it could not be reproduced. > From the shared stack traces it looked like Postcopy thread was > preparing to finish before migrating all the pages. The issue is that a zero page is being migrated by multifd but there's an optimization in place that skips faulting the page in on the destination. Later during postcopy when the page is found to be missing, postcopy (@migrate_send_rp_req_pages) believes the page is already present due to the receivedmap for that pfn being set and thus the code accessing the guest memory just sits there waiting for the page. It seems your series has a logical conflict with this work that was done a while back: https://lore.kernel.org/all/20240401154110.2028453-1-yuan1.liu@intel.com/ The usage of receivedmap for multifd was supposed to be mutually exclusive with postcopy. Take a look at the description of that series and at postcopy_place_page_zero(). We need to figure out what needs to change and how to do that compatibly. It might just be the case of memsetting the zero page always for postcopy, but I havent't thought too much about it. There's also other issues with the series: https://gitlab.com/farosas/qemu/-/pipelines/1770488059 The CI workers don't support userfaultfd so the tests need to check for that properly. We have MigrationTestEnv::has_uffd for that. Lastly, I have seem some weirdness with TLS channels disconnections leading to asserts in qio_channel_shutdown() in my testing. I'll get a better look at those tomorrow. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-16 0:31 ` [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Fabiano Rosas @ 2025-04-16 12:59 ` Fabiano Rosas 2025-04-17 11:13 ` Prasad Pandit 0 siblings, 1 reply; 29+ messages in thread From: Fabiano Rosas @ 2025-04-16 12:59 UTC (permalink / raw) To: Prasad Pandit, qemu-devel; +Cc: peterx, berrange, Prasad Pandit Fabiano Rosas <farosas@suse.de> writes: > Prasad Pandit <ppandit@redhat.com> writes: > >> From: Prasad Pandit <pjp@fedoraproject.org> >> >> Hello, >> >> >> * This series (v9) does minor refactoring and reordering changes as >> suggested in the review of earlier series (v8). Also tried to >> reproduce/debug a qtest hang issue, but it could not be reproduced. >> From the shared stack traces it looked like Postcopy thread was >> preparing to finish before migrating all the pages. > > The issue is that a zero page is being migrated by multifd but there's > an optimization in place that skips faulting the page in on the > destination. Later during postcopy when the page is found to be missing, > postcopy (@migrate_send_rp_req_pages) believes the page is already > present due to the receivedmap for that pfn being set and thus the code > accessing the guest memory just sits there waiting for the page. > > It seems your series has a logical conflict with this work that was done > a while back: > > https://lore.kernel.org/all/20240401154110.2028453-1-yuan1.liu@intel.com/ > > The usage of receivedmap for multifd was supposed to be mutually > exclusive with postcopy. Take a look at the description of that series > and at postcopy_place_page_zero(). We need to figure out what needs to > change and how to do that compatibly. It might just be the case of > memsetting the zero page always for postcopy, but I havent't thought too > much about it. > > There's also other issues with the series: > > https://gitlab.com/farosas/qemu/-/pipelines/1770488059 > > The CI workers don't support userfaultfd so the tests need to check for > that properly. We have MigrationTestEnv::has_uffd for that. > > Lastly, I have seem some weirdness with TLS channels disconnections > leading to asserts in qio_channel_shutdown() in my testing. I'll get a > better look at those tomorrow. Ok, you can ignore this last paragraph. I was seeing the postcopy recovery test disconnect messages, those are benign. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-16 12:59 ` Fabiano Rosas @ 2025-04-17 11:13 ` Prasad Pandit 2025-04-17 16:05 ` Fabiano Rosas 0 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-17 11:13 UTC (permalink / raw) To: Fabiano Rosas; +Cc: qemu-devel, peterx, berrange, Prasad Pandit Hi, On Wed, 16 Apr 2025 at 18:29, Fabiano Rosas <farosas@suse.de> wrote: > > The issue is that a zero page is being migrated by multifd but there's > > an optimization in place that skips faulting the page in on the > > destination. Later during postcopy when the page is found to be missing, > > postcopy (@migrate_send_rp_req_pages) believes the page is already > > present due to the receivedmap for that pfn being set and thus the code > > accessing the guest memory just sits there waiting for the page. > > > > It seems your series has a logical conflict with this work that was done > > a while back: > > > > https://lore.kernel.org/all/20240401154110.2028453-1-yuan1.liu@intel.com/ > > > > The usage of receivedmap for multifd was supposed to be mutually > > exclusive with postcopy. Take a look at the description of that series > > and at postcopy_place_page_zero(). We need to figure out what needs to > > change and how to do that compatibly. It might just be the case of > > memsetting the zero page always for postcopy, but I havent't thought too > > much about it. === $ grep -i avx /proc/cpuinfo flags : avx avx2 avx512f avx512dq avx512ifma avx512cd avx512bw avx512vl avx512vbmi avx512_vbmi2 avx512_vnni avx512_bitalg avx512_vpopcntdq avx512_vp2intersect $ $ ./configure --enable-kvm --enable-avx512bw --enable-avx2 --disable-docs --target-list='x86_64-softmmu' $ make -sj10 check-qtest 67/67 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 193.80s 81 subtests passed === * One of my machines does seem to support 'avx*' instructions. QEMU is configured and built with the 'avx2' and 'avx512bw' support. Still migration-tests run fine, without any hang issue observed. Not sure why the hang issue is not reproducing on my side. How do you generally build QEMU to run these tests? Does this issue require some specific h/w setup/support? * Not sure how/why page faults happen during the Multifd phase when the guest on the destination is not running. If 'receivedmap' says that page is present, code accessing guest memory should just access whatever is available/present in that space, without waiting. I'll try to see what zero pages do, how page-faults occur during postcopy and how they are serviced. Let's see.. * Another suggestion is, maybe we should review and pull at least the refactoring patches so that in the next revisions we don't have to redo them. We can hold back the "enable multifd and postcopy together" patch that causes this guest hang issue to surface. > > There's also other issues with the series: > > > > https://gitlab.com/farosas/qemu/-/pipelines/1770488059 > > > > The CI workers don't support userfaultfd so the tests need to check for > > that properly. We have MigrationTestEnv::has_uffd for that. > > > > Lastly, I have seem some weirdness with TLS channels disconnections > > leading to asserts in qio_channel_shutdown() in my testing. I'll get a > > better look at those tomorrow. > > Ok, you can ignore this last paragraph. I was seeing the postcopy > recovery test disconnect messages, those are benign. * ie. ignore everything after - "There's also other issues with this series: " ? OR just the last one " ...with TLS channels..." ?? Postcopy tests are added only if (env->has_uffd) check returns true. Thank you. --- - Prasad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-17 11:13 ` Prasad Pandit @ 2025-04-17 16:05 ` Fabiano Rosas 2025-04-23 22:50 ` Peter Xu 0 siblings, 1 reply; 29+ messages in thread From: Fabiano Rosas @ 2025-04-17 16:05 UTC (permalink / raw) To: Prasad Pandit; +Cc: qemu-devel, peterx, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > Hi, > > On Wed, 16 Apr 2025 at 18:29, Fabiano Rosas <farosas@suse.de> wrote: >> > The issue is that a zero page is being migrated by multifd but there's >> > an optimization in place that skips faulting the page in on the >> > destination. Later during postcopy when the page is found to be missing, >> > postcopy (@migrate_send_rp_req_pages) believes the page is already >> > present due to the receivedmap for that pfn being set and thus the code >> > accessing the guest memory just sits there waiting for the page. >> > >> > It seems your series has a logical conflict with this work that was done >> > a while back: >> > >> > https://lore.kernel.org/all/20240401154110.2028453-1-yuan1.liu@intel.com/ >> > >> > The usage of receivedmap for multifd was supposed to be mutually >> > exclusive with postcopy. Take a look at the description of that series >> > and at postcopy_place_page_zero(). We need to figure out what needs to >> > change and how to do that compatibly. It might just be the case of >> > memsetting the zero page always for postcopy, but I havent't thought too >> > much about it. > > === > $ grep -i avx /proc/cpuinfo > flags : avx avx2 avx512f avx512dq avx512ifma avx512cd avx512bw > avx512vl avx512vbmi avx512_vbmi2 avx512_vnni avx512_bitalg > avx512_vpopcntdq avx512_vp2intersect > $ > $ ./configure --enable-kvm --enable-avx512bw --enable-avx2 > --disable-docs --target-list='x86_64-softmmu' > $ make -sj10 check-qtest > 67/67 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test > OK 193.80s 81 subtests passed > === > > * One of my machines does seem to support 'avx*' instructions. QEMU is > configured and built with the 'avx2' and 'avx512bw' support. Still > migration-tests run fine, without any hang issue observed. Not sure > why the hang issue is not reproducing on my side. How do you generally > build QEMU to run these tests? Does this issue require some specific > h/w setup/support? > There's nothing unusual here that I know of. Configure line is just --target-list=x86_64-softmmu --enable-debug --disable-docs --disable-plugins. > * Not sure how/why page faults happen during the Multifd phase when > the guest on the destination is not running. If 'receivedmap' says > that page is present, code accessing guest memory should just access > whatever is available/present in that space, without waiting. I'll try > to see what zero pages do, how page-faults occur during postcopy and > how they are serviced. Let's see.. It's not that page faults happen during multifd. The page was already sent during precopy, but multifd-recv didn't write to it, it just marked the receivedmap. When postcopy starts, the page gets accessed and faults. Since postcopy is on, the migration wants to request the page from the source, but it's present in the receivedmap, so it doesn't ask. No page ever comes and the code hangs waiting for the page fault to be serviced (or potentially faults continuously? I'm not sure on the details). > > * Another suggestion is, maybe we should review and pull at least the > refactoring patches so that in the next revisions we don't have to > redo them. We can hold back the "enable multifd and postcopy together" > patch that causes this guest hang issue to surface. > That's reasonable. But I won't be available for the next two weeks. Peter is going to be back in the meantime, let's hear what he has to say about this postcopy issue. I'll provide my r-bs. >> > There's also other issues with the series: >> > >> > https://gitlab.com/farosas/qemu/-/pipelines/1770488059 >> > >> > The CI workers don't support userfaultfd so the tests need to check for >> > that properly. We have MigrationTestEnv::has_uffd for that. >> > >> > Lastly, I have seem some weirdness with TLS channels disconnections >> > leading to asserts in qio_channel_shutdown() in my testing. I'll get a >> > better look at those tomorrow. >> >> Ok, you can ignore this last paragraph. I was seeing the postcopy >> recovery test disconnect messages, those are benign. > > * ie. ignore everything after - "There's also other issues with this > series: " ? OR just the last one " ...with TLS channels..." ?? > Postcopy tests are added only if (env->has_uffd) check returns true. > Only the TLS part. The CI is failing with just this series. I didn't change anything there. Maybe there's a bug in the userfaultfd detection? I'll leave it to you, here's the error: # Running /ppc64/migration/multifd+postcopy/tcp/plain/cancel # Using machine type: pseries-10.0 # starting QEMU: exec ./qemu-system-ppc64 -qtest # unix:/tmp/qtest-1305.sock -qtest-log /dev/null -chardev # socket,path=/tmp/qtest-1305.qmp,id=char0 -mon # chardev=char0,mode=control -display none -audio none -accel kvm -accel # tcg -machine pseries-10.0,vsmt=8 -name source,debug-threads=on -m 256M # -serial file:/tmp/migration-test-X0SO42/src_serial -nodefaults # -machine # cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,cap-ccf-assist=off, # -bios /tmp/migration-test-X0SO42/bootsect 2>/dev/null -accel qtest # starting QEMU: exec ./qemu-system-ppc64 -qtest # unix:/tmp/qtest-1305.sock -qtest-log /dev/null -chardev # socket,path=/tmp/qtest-1305.qmp,id=char0 -mon # chardev=char0,mode=control -display none -audio none -accel kvm -accel # tcg -machine pseries-10.0,vsmt=8 -name target,debug-threads=on -m 256M # -serial file:/tmp/migration-test-X0SO42/dest_serial -incoming defer # -nodefaults -machine # cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,cap-ccf-assist=off, # -bios /tmp/migration-test-X0SO42/bootsect 2>/dev/null -accel qtest # { # "error": { # "class": "GenericError", # "desc": "Postcopy is not supported: Userfaultfd not available: Function not implemented" # } # } ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-17 16:05 ` Fabiano Rosas @ 2025-04-23 22:50 ` Peter Xu 2025-04-29 12:51 ` Prasad Pandit 0 siblings, 1 reply; 29+ messages in thread From: Peter Xu @ 2025-04-23 22:50 UTC (permalink / raw) To: Fabiano Rosas; +Cc: Prasad Pandit, qemu-devel, berrange, Prasad Pandit On Thu, Apr 17, 2025 at 01:05:37PM -0300, Fabiano Rosas wrote: > It's not that page faults happen during multifd. The page was already > sent during precopy, but multifd-recv didn't write to it, it just marked > the receivedmap. When postcopy starts, the page gets accessed and > faults. Since postcopy is on, the migration wants to request the page > from the source, but it's present in the receivedmap, so it doesn't > ask. No page ever comes and the code hangs waiting for the page fault to > be serviced (or potentially faults continuously? I'm not sure on the > details). I think your previous analysis is correct on the zero pages. I am not 100% sure if that's the issue but very likely. I tend to also agree with you that we could skip zero page optimization in multifd code when postcopy is enabled (maybe plus some comment right above..). Thanks, -- Peter Xu ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-23 22:50 ` Peter Xu @ 2025-04-29 12:51 ` Prasad Pandit 2025-04-29 13:04 ` Peter Xu 2025-05-05 19:04 ` Fabiano Rosas 0 siblings, 2 replies; 29+ messages in thread From: Prasad Pandit @ 2025-04-29 12:51 UTC (permalink / raw) To: Peter Xu; +Cc: Fabiano Rosas, qemu-devel, berrange, Prasad Pandit Hi, > On Thu, Apr 17, 2025 at 01:05:37PM -0300, Fabiano Rosas wrote: > > It's not that page faults happen during multifd. The page was already > > sent during precopy, but multifd-recv didn't write to it, it just marked > > the receivedmap. When postcopy starts, the page gets accessed and > > faults. Since postcopy is on, the migration wants to request the page > > from the source, but it's present in the receivedmap, so it doesn't > > ask. No page ever comes and the code hangs waiting for the page fault to > > be serviced (or potentially faults continuously? I'm not sure on the > > details). > > I think your previous analysis is correct on the zero pages. I am not 100% > sure if that's the issue but very likely. I tend to also agree with you > that we could skip zero page optimization in multifd code when postcopy is > enabled (maybe plus some comment right above..). migration/multifd: solve zero page causing multiple page faults -> https://gitlab.com/qemu-project/qemu/-/commit/5ef7e26bdb7eda10d6d5e1b77121be9945e5e550 * Is this the optimization that is causing the migration hang issue? === diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c index dbc1184921..00f69ff965 100644 --- a/migration/multifd-zero-page.c +++ b/migration/multifd-zero-page.c @@ -85,7 +85,8 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) { for (int i = 0; i < p->zero_num; i++) { void *page = p->host + p->zero[i]; - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { + if (!migrate_postcopy() && + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { memset(page, 0, multifd_ram_page_size()); } else { ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); === * Would the above patch help to resolve it? * Another way could be when the page fault occurs during postcopy phase, if we know (from receivedmap) that the faulted page is a zero-page, maybe we could write it locally on the destination to service the page-fault? On Thu, 17 Apr 2025 at 21:35, Fabiano Rosas <farosas@suse.de> wrote: > Maybe there's a bug in the userfaultfd detection? I'll leave it to you, here's the error: > > # Running /ppc64/migration/multifd+postcopy/tcp/plain/cancel > # Using machine type: pseries-10.0 > # starting QEMU: exec ./qemu-system-ppc64 -qtest > # { > # "error": { > # "class": "GenericError", > # "desc": "Postcopy is not supported: Userfaultfd not available: Function not implemented" > # } > # } * It is saying - function not implemented - does the Pseries machine not support userfaultfd? Thank you. --- - Prasad ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 12:51 ` Prasad Pandit @ 2025-04-29 13:04 ` Peter Xu 2025-04-29 13:28 ` Prasad Pandit 2025-05-05 19:04 ` Fabiano Rosas 1 sibling, 1 reply; 29+ messages in thread From: Peter Xu @ 2025-04-29 13:04 UTC (permalink / raw) To: Prasad Pandit; +Cc: Fabiano Rosas, qemu-devel, berrange, Prasad Pandit On Tue, Apr 29, 2025 at 06:21:13PM +0530, Prasad Pandit wrote: > Hi, > > > On Thu, Apr 17, 2025 at 01:05:37PM -0300, Fabiano Rosas wrote: > > > It's not that page faults happen during multifd. The page was already > > > sent during precopy, but multifd-recv didn't write to it, it just marked > > > the receivedmap. When postcopy starts, the page gets accessed and > > > faults. Since postcopy is on, the migration wants to request the page > > > from the source, but it's present in the receivedmap, so it doesn't > > > ask. No page ever comes and the code hangs waiting for the page fault to > > > be serviced (or potentially faults continuously? I'm not sure on the > > > details). > > > > I think your previous analysis is correct on the zero pages. I am not 100% > > sure if that's the issue but very likely. I tend to also agree with you > > that we could skip zero page optimization in multifd code when postcopy is > > enabled (maybe plus some comment right above..). > > migration/multifd: solve zero page causing multiple page faults > -> https://gitlab.com/qemu-project/qemu/-/commit/5ef7e26bdb7eda10d6d5e1b77121be9945e5e550 > > * Is this the optimization that is causing the migration hang issue? I think that's what Fabiano mentioned, but ultimately we need to verify it on a reproducer to know. > > === > diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c > index dbc1184921..00f69ff965 100644 > --- a/migration/multifd-zero-page.c > +++ b/migration/multifd-zero-page.c > @@ -85,7 +85,8 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) > { > for (int i = 0; i < p->zero_num; i++) { > void *page = p->host + p->zero[i]; > - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > + if (!migrate_postcopy() && > + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > memset(page, 0, multifd_ram_page_size()); > } else { > ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); > === > > * Would the above patch help to resolve it? Looks ok, but please add some comments explain why postcopy needs to do it, and especially do it during precopy phase. I'd use migrate_postcopy_ram() instead. I wished migrate_dirty_bitmaps() has a better name, maybe migrate_postcopy_block().. I have totally no idea who is using the feature, especially when postcopy-ram is off. > > * Another way could be when the page fault occurs during postcopy > phase, if we know (from receivedmap) that the faulted page is a > zero-page, maybe we could write it locally on the destination to > service the page-fault? I don't think we can know that - receivedmap set doesn't mean it's a zero page, but only says it's been received before. It can also happen e.g. >1 threads faulted on the same page then the 2nd thread faulted on it may see receivedmap set because the 1st thread got faulted already got the fault resolved. -- Peter Xu ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 13:04 ` Peter Xu @ 2025-04-29 13:28 ` Prasad Pandit 2025-04-29 13:47 ` Peter Xu 2025-05-05 19:01 ` Fabiano Rosas 0 siblings, 2 replies; 29+ messages in thread From: Prasad Pandit @ 2025-04-29 13:28 UTC (permalink / raw) To: Peter Xu; +Cc: Fabiano Rosas, qemu-devel, berrange, Prasad Pandit On Tue, 29 Apr 2025 at 18:34, Peter Xu <peterx@redhat.com> wrote: > I think that's what Fabiano mentioned, but ultimately we need to verify it > on a reproducer to know. ... > Looks ok, but please add some comments explain why postcopy needs to do it, > and especially do it during precopy phase. > > I'd use migrate_postcopy_ram() instead. * Okay. It should be '||' instead of '&&' in the first conditional I think, we want to write zeropage when postcopy is enabled. === diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c index dbc1184921..4d6677feab 100644 --- a/migration/multifd-zero-page.c +++ b/migration/multifd-zero-page.c @@ -85,9 +85,11 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) { for (int i = 0; i < p->zero_num; i++) { void *page = p->host + p->zero[i]; - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { + if (migrate_postcopy_ram() || + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { memset(page, 0, multifd_ram_page_size()); - } else { + } + if (!ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); } } === * I'll send this one if it looks okay. > I don't think we can know that - receivedmap set doesn't mean it's a zero > page, but only says it's been received before. It can also happen e.g. >1 > threads faulted on the same page then the 2nd thread faulted on it may see > receivedmap set because the 1st thread got faulted already got the fault > resolved. * Okay. Thank you. --- - Prasad ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 13:28 ` Prasad Pandit @ 2025-04-29 13:47 ` Peter Xu 2025-04-29 15:20 ` Prasad Pandit 2025-05-05 19:01 ` Fabiano Rosas 1 sibling, 1 reply; 29+ messages in thread From: Peter Xu @ 2025-04-29 13:47 UTC (permalink / raw) To: Prasad Pandit; +Cc: Fabiano Rosas, qemu-devel, berrange, Prasad Pandit On Tue, Apr 29, 2025 at 06:58:29PM +0530, Prasad Pandit wrote: > On Tue, 29 Apr 2025 at 18:34, Peter Xu <peterx@redhat.com> wrote: > > I think that's what Fabiano mentioned, but ultimately we need to verify it > > on a reproducer to know. > ... > > Looks ok, but please add some comments explain why postcopy needs to do it, > > and especially do it during precopy phase. > > > > I'd use migrate_postcopy_ram() instead. > > * Okay. It should be '||' instead of '&&' in the first conditional I > think, we want to write zeropage when postcopy is enabled. > === > diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c > index dbc1184921..4d6677feab 100644 > --- a/migration/multifd-zero-page.c > +++ b/migration/multifd-zero-page.c > @@ -85,9 +85,11 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) > { > for (int i = 0; i < p->zero_num; i++) { > void *page = p->host + p->zero[i]; > - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > + if (migrate_postcopy_ram() || > + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > memset(page, 0, multifd_ram_page_size()); > - } else { > + } > + if (!ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); > } > } > === > * I'll send this one if it looks okay. Please don't rush to send. Again, let's verify the issue first before resending anything. If you could reproduce it it would be perfect, then we can already verify it. Otherwise we may need help from Fabiano. Let's not send anything if you're not yet sure whether it works.. It can confuse people thinking problem solved, but maybe not yet. -- Peter Xu ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 13:47 ` Peter Xu @ 2025-04-29 15:20 ` Prasad Pandit 2025-04-29 15:49 ` Peter Xu 0 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-04-29 15:20 UTC (permalink / raw) To: Peter Xu; +Cc: Fabiano Rosas, qemu-devel, berrange, Prasad Pandit On Tue, 29 Apr 2025 at 19:18, Peter Xu <peterx@redhat.com> wrote: > Please don't rush to send. Again, let's verify the issue first before > resending anything. > > If you could reproduce it it would be perfect, then we can already verify > it. Otherwise we may need help from Fabiano. Let's not send anything if > you're not yet sure whether it works.. It can confuse people thinking > problem solved, but maybe not yet. * No, the migration hang issue is not reproducing on my side. Earlier in this thread, Fabiano said you'll be better able to confirm the issue. (so its possible fix as well I guess) * You don't have access to the set-up that he uses for running tests and merging patches? Would it be possible for you to run the same tests? (just checking, I don't know how co-maintainers work to test/merge patches) * If we don't send the patch, how will Fabiano test it? Should we wait for Fabiano to come back and then make this same patch in his set-up and test/verify it? Thank you. --- - Prasad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 15:20 ` Prasad Pandit @ 2025-04-29 15:49 ` Peter Xu 0 siblings, 0 replies; 29+ messages in thread From: Peter Xu @ 2025-04-29 15:49 UTC (permalink / raw) To: Prasad Pandit; +Cc: Fabiano Rosas, qemu-devel, berrange, Prasad Pandit On Tue, Apr 29, 2025 at 08:50:19PM +0530, Prasad Pandit wrote: > On Tue, 29 Apr 2025 at 19:18, Peter Xu <peterx@redhat.com> wrote: > > Please don't rush to send. Again, let's verify the issue first before > > resending anything. > > > > If you could reproduce it it would be perfect, then we can already verify > > it. Otherwise we may need help from Fabiano. Let's not send anything if > > you're not yet sure whether it works.. It can confuse people thinking > > problem solved, but maybe not yet. > > * No, the migration hang issue is not reproducing on my side. Earlier > in this thread, Fabiano said you'll be better able to confirm the > issue. (so its possible fix as well I guess) > > * You don't have access to the set-up that he uses for running tests > and merging patches? Would it be possible for you to run the same > tests? (just checking, I don't know how co-maintainers work to > test/merge patches) No I don't. > > * If we don't send the patch, how will Fabiano test it? Should we wait > for Fabiano to come back and then make this same patch in his set-up > and test/verify it? I thought you've provided a diff. That would be good enough for verifications. If you really want, you can repost, but please mention explicitly that you haven't verified the issue, so the patchset needs to be verified. Fabiano should come back early May. If you want, you can try to look into how to reproduce it by looking at why it triggered in vapic path: https://lore.kernel.org/all/87plhwgbu6.fsf@suse.de/#t Thread 1 (Thread 0x7fbc4849df80 (LWP 7487) "qemu-system-x86"): #0 __memcpy_evex_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:274 #1 0x0000560b135103aa in flatview_read_continue_step (attrs=..., buf=0x560b168a5930 "U\252\022\006\016\a1\300\271", len=9216, mr_addr=831488, l=0x7fbc465ff980, mr=0x560b166c5070) at ../system/physmem.c:3056 #2 0x0000560b1351042e in flatview_read_continue (fv=0x560b16c606a0, addr=831488, attrs=..., ptr=0x560b168a5930, len=9216, mr_addr=831488, l=9216, mr=0x560b166c5070) at ../system/physmem.c:3073 #3 0x0000560b13510533 in flatview_read (fv=0x560b16c606a0, addr=831488, attrs=..., buf=0x560b168a5930, len=9216) at ../system/physmem.c:3103 #4 0x0000560b135105be in address_space_read_full (as=0x560b14970fc0 <address_space_memory>, addr=831488, attrs=..., buf=0x560b168a5930, len=9216) at ../system/physmem.c:3116 #5 0x0000560b135106e7 in address_space_rw (as=0x560b14970fc0 <address_space_memory>, addr=831488, attrs=..., buf=0x560b168a5930, len=9216, is_write=false) at ../system/physmem.c:3144 #6 0x0000560b13510848 in cpu_physical_memory_rw (addr=831488, buf=0x560b168a5930, len=9216, is_write=false) at ../system/physmem.c:3170 #7 0x0000560b1338f5a5 in cpu_physical_memory_read (addr=831488, buf=0x560b168a5930, len=9216) at qemu/include/exec/cpu-common.h:148 #8 0x0000560b1339063c in patch_hypercalls (s=0x560b168840c0) at ../hw/i386/vapic.c:547 #9 0x0000560b1339096d in vapic_prepare (s=0x560b168840c0) at ../hw/i386/vapic.c:629 #10 0x0000560b13390e8b in vapic_post_load (opaque=0x560b168840c0, version_id=1) at ../hw/i386/vapic.c:789 #11 0x0000560b135b4924 in vmstate_load_state (f=0x560b16c53400, vmsd=0x560b147c6cc0 <vmstate_vapic>, opaque=0x560b168840c0, version_id=1) at ../migration/vmstate.c:234 #12 0x0000560b132a15b8 in vmstate_load (f=0x560b16c53400, se=0x560b16893390) at ../migration/savevm.c:972 #13 0x0000560b132a4f28 in qemu_loadvm_section_start_full (f=0x560b16c53400, type=4 '\004') at ../migration/savevm.c:2746 #14 0x0000560b132a5ae8 in qemu_loadvm_state_main (f=0x560b16c53400, mis=0x560b16877f20) at ../migration/savevm.c:3058 #15 0x0000560b132a45d0 in loadvm_handle_cmd_packaged (mis=0x560b16877f20) at ../migration/savevm.c:2451 #16 0x0000560b132a4b36 in loadvm_process_command (f=0x560b168c3b60) at ../migration/savevm.c:2614 #17 0x0000560b132a5b96 in qemu_loadvm_state_main (f=0x560b168c3b60, mis=0x560b16877f20) at ../migration/savevm.c:3073 #18 0x0000560b132a5db7 in qemu_loadvm_state (f=0x560b168c3b60) at ../migration/savevm.c:3150 #19 0x0000560b13286271 in process_incoming_migration_co (opaque=0x0) at ../migration/migration.c:892 #20 0x0000560b137cb6d4 in coroutine_trampoline (i0=377836416, i1=22027) at ../util/coroutine-ucontext.c:175 #21 0x00007fbc4786a79e in ??? () at ../sysdeps/unix/sysv/linux/x86_64/__start_context.S:103 So _if_ the theory is correct, vapic's patch_hypercalls() might be reading a zero page (with GPA 831488, over len=9216, which IIUC covers three pages). Maybe you can check when it'll be one zero page and when it will be not, then maybe you can figure out how you make it always a zero page hence reliably trigger a hang in post_load. You could also try to write a program in guest, zeroing most pages first, trigger migrate (hence send zero pages during multifd precopy), start postcopy, then you should be able to observe vcpu hang at least before postcopy completes. However I don't think it'll hang forever, since if migration all completes, UFFDIO_UNREGISTER will remove the userfaultfd trackings and then kick all hang threads out, causing the fault to be resolved right at the completion of postcopy. So it won't really hang forever like what Fabiano reported here. Meanwhile we'll always want to verify the original reproducer.. even if you could hang it temporarily in a vcpu thread. Thanks, -- Peter Xu ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 13:28 ` Prasad Pandit 2025-04-29 13:47 ` Peter Xu @ 2025-05-05 19:01 ` Fabiano Rosas 2025-05-06 12:32 ` Prasad Pandit 1 sibling, 1 reply; 29+ messages in thread From: Fabiano Rosas @ 2025-05-05 19:01 UTC (permalink / raw) To: Prasad Pandit, Peter Xu; +Cc: qemu-devel, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > On Tue, 29 Apr 2025 at 18:34, Peter Xu <peterx@redhat.com> wrote: >> I think that's what Fabiano mentioned, but ultimately we need to verify it >> on a reproducer to know. > ... >> Looks ok, but please add some comments explain why postcopy needs to do it, >> and especially do it during precopy phase. >> >> I'd use migrate_postcopy_ram() instead. > > * Okay. It should be '||' instead of '&&' in the first conditional I > think, we want to write zeropage when postcopy is enabled. > === > diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c > index dbc1184921..4d6677feab 100644 > --- a/migration/multifd-zero-page.c > +++ b/migration/multifd-zero-page.c > @@ -85,9 +85,11 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) > { > for (int i = 0; i < p->zero_num; i++) { > void *page = p->host + p->zero[i]; > - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > + if (migrate_postcopy_ram() || > + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > memset(page, 0, multifd_ram_page_size()); > - } else { > + } > + if (!ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); > } > } > === I applied this diff and I'm not seeing the hang anymore. ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-05-05 19:01 ` Fabiano Rosas @ 2025-05-06 12:32 ` Prasad Pandit 0 siblings, 0 replies; 29+ messages in thread From: Prasad Pandit @ 2025-05-06 12:32 UTC (permalink / raw) To: Fabiano Rosas; +Cc: Peter Xu, qemu-devel, berrange, Prasad Pandit Hello Fabiano, On Tue, 6 May 2025 at 00:31, Fabiano Rosas <farosas@suse.de> wrote: > > +++ b/migration/multifd-zero-page.c > > @@ -85,9 +85,11 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) > > { > > for (int i = 0; i < p->zero_num; i++) { > > void *page = p->host + p->zero[i]; > > - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > > + if (migrate_postcopy_ram() || > > + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > > memset(page, 0, multifd_ram_page_size()); > > - } else { > > + } > > + if (!ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > > ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); > > } > > } > > === > > I applied this diff and I'm not seeing the hang anymore. * Great, thank you for the confirmation. I'll prepare a formal patch. Thank you. --- - Prasad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-04-29 12:51 ` Prasad Pandit 2025-04-29 13:04 ` Peter Xu @ 2025-05-05 19:04 ` Fabiano Rosas 2025-05-06 12:38 ` Prasad Pandit 1 sibling, 1 reply; 29+ messages in thread From: Fabiano Rosas @ 2025-05-05 19:04 UTC (permalink / raw) To: Prasad Pandit, Peter Xu; +Cc: qemu-devel, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > Hi, > >> On Thu, Apr 17, 2025 at 01:05:37PM -0300, Fabiano Rosas wrote: >> > It's not that page faults happen during multifd. The page was already >> > sent during precopy, but multifd-recv didn't write to it, it just marked >> > the receivedmap. When postcopy starts, the page gets accessed and >> > faults. Since postcopy is on, the migration wants to request the page >> > from the source, but it's present in the receivedmap, so it doesn't >> > ask. No page ever comes and the code hangs waiting for the page fault to >> > be serviced (or potentially faults continuously? I'm not sure on the >> > details). >> >> I think your previous analysis is correct on the zero pages. I am not 100% >> sure if that's the issue but very likely. I tend to also agree with you >> that we could skip zero page optimization in multifd code when postcopy is >> enabled (maybe plus some comment right above..). > > migration/multifd: solve zero page causing multiple page faults > -> https://gitlab.com/qemu-project/qemu/-/commit/5ef7e26bdb7eda10d6d5e1b77121be9945e5e550 > > * Is this the optimization that is causing the migration hang issue? > > === > diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c > index dbc1184921..00f69ff965 100644 > --- a/migration/multifd-zero-page.c > +++ b/migration/multifd-zero-page.c > @@ -85,7 +85,8 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p) > { > for (int i = 0; i < p->zero_num; i++) { > void *page = p->host + p->zero[i]; > - if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > + if (!migrate_postcopy() && > + ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) { > memset(page, 0, multifd_ram_page_size()); > } else { > ramblock_recv_bitmap_set_offset(p->block, p->zero[i]); > === > > * Would the above patch help to resolve it? > > * Another way could be when the page fault occurs during postcopy > phase, if we know (from receivedmap) that the faulted page is a > zero-page, maybe we could write it locally on the destination to > service the page-fault? > > On Thu, 17 Apr 2025 at 21:35, Fabiano Rosas <farosas@suse.de> wrote: >> Maybe there's a bug in the userfaultfd detection? I'll leave it to you, here's the error: >> >> # Running /ppc64/migration/multifd+postcopy/tcp/plain/cancel >> # Using machine type: pseries-10.0 >> # starting QEMU: exec ./qemu-system-ppc64 -qtest >> # { >> # "error": { >> # "class": "GenericError", >> # "desc": "Postcopy is not supported: Userfaultfd not available: Function not implemented" >> # } >> # } > > * It is saying - function not implemented - does the Pseries machine > not support userfaultfd? > We're missing a check on has_uffd for the multifd+postcopy tests. > Thank you. > --- > - Prasad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-05-05 19:04 ` Fabiano Rosas @ 2025-05-06 12:38 ` Prasad Pandit 2025-05-06 13:40 ` Fabiano Rosas 0 siblings, 1 reply; 29+ messages in thread From: Prasad Pandit @ 2025-05-06 12:38 UTC (permalink / raw) To: Fabiano Rosas; +Cc: Peter Xu, qemu-devel, berrange, Prasad Pandit Hi, On Tue, 6 May 2025 at 00:34, Fabiano Rosas <farosas@suse.de> wrote: > >> # Running /ppc64/migration/multifd+postcopy/tcp/plain/cancel > >> # Using machine type: pseries-10.0 > >> # starting QEMU: exec ./qemu-system-ppc64 -qtest > >> # { > >> # "error": { > >> # "class": "GenericError", > >> # "desc": "Postcopy is not supported: Userfaultfd not available: Function not implemented" > >> # } > >> # } > > === [ ~]# ... PPC KVM module is not loaded. Try modprobe kvm_hv. qemu-system-ppc64: -accel kvm: failed to initialize kvm: Invalid argument qemu-system-ppc64: -accel kvm: ioctl(KVM_CREATE_VM) failed: Invalid argument PPC KVM module is not loaded. Try modprobe kvm_hv. qemu-system-ppc64: -accel kvm: failed to initialize kvm: Invalid argument [ ~]# [ ~]# modprobe kvm-hv modprobe: ERROR: could not insert 'kvm_hv': No such device [ ~]# [ ~]# ls -l /dev/kvm /dev/userfaultfd crw-rw-rw-. 1 root kvm 10, 232 May 6 07:06 /dev/kvm crw----rw-. 1 root root 10, 123 May 6 06:30 /dev/userfaultfd [ ~]# === * I tried to reproduce this issue across multiple Power9 and Power10 machines, but I -qtest could not run due to above errors. > We're missing a check on has_uffd for the multifd+postcopy tests. * If it is about missing the 'e->has_uffd' check, does that mean Postcopy tests are skipped on this machine because 'e->has_uffd' is false? Thank you. --- - Prasad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 0/7] Allow to enable multifd and postcopy migration together 2025-05-06 12:38 ` Prasad Pandit @ 2025-05-06 13:40 ` Fabiano Rosas 0 siblings, 0 replies; 29+ messages in thread From: Fabiano Rosas @ 2025-05-06 13:40 UTC (permalink / raw) To: Prasad Pandit; +Cc: Peter Xu, qemu-devel, berrange, Prasad Pandit Prasad Pandit <ppandit@redhat.com> writes: > Hi, > > On Tue, 6 May 2025 at 00:34, Fabiano Rosas <farosas@suse.de> wrote: >> >> # Running /ppc64/migration/multifd+postcopy/tcp/plain/cancel >> >> # Using machine type: pseries-10.0 >> >> # starting QEMU: exec ./qemu-system-ppc64 -qtest >> >> # { >> >> # "error": { >> >> # "class": "GenericError", >> >> # "desc": "Postcopy is not supported: Userfaultfd not available: Function not implemented" >> >> # } >> >> # } >> > > === > [ ~]# > ... > PPC KVM module is not loaded. Try modprobe kvm_hv. > qemu-system-ppc64: -accel kvm: failed to initialize kvm: Invalid argument > qemu-system-ppc64: -accel kvm: ioctl(KVM_CREATE_VM) failed: Invalid argument > PPC KVM module is not loaded. Try modprobe kvm_hv. > qemu-system-ppc64: -accel kvm: failed to initialize kvm: Invalid argument The tests should fallback to TCG and that should be enough to reproduce this issue. I don't think you even need a ppc machine, the CI uses a x86_64 container. > [ ~]# > > [ ~]# modprobe kvm-hv > modprobe: ERROR: could not insert 'kvm_hv': No such device > [ ~]# > [ ~]# ls -l /dev/kvm /dev/userfaultfd > crw-rw-rw-. 1 root kvm 10, 232 May 6 07:06 /dev/kvm > crw----rw-. 1 root root 10, 123 May 6 06:30 /dev/userfaultfd > [ ~]# > === > > * I tried to reproduce this issue across multiple Power9 and Power10 > machines, but I -qtest could not run due to above errors. > There are several considerations to take into account with ppc64le, you probably have either a distro version that doesn't provide the KVM module or a machine that doesn't have KVM support at all. >> We're missing a check on has_uffd for the multifd+postcopy tests. > > * If it is about missing the 'e->has_uffd' check, does that mean > Postcopy tests are skipped on this machine because 'e->has_uffd' is > false? > I haven't verified, but yes, the ones that check has_uffd should be skipped. I don't think you need to go to the extent to reproduce this. Look at migrate_caps_check(), whenever postcopy-ram is enabled for the first time, it will call postcopy_ram_supported_by_host(), so it follows that any test that enables postcopy-ram must first check env->has_uffd. > > Thank you. > --- > - Prasad ^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2025-05-06 13:41 UTC | newest] Thread overview: 29+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-11 11:45 [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 1/7] migration/multifd: move macros to multifd header Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 2/7] migration: refactor channel discovery mechanism Prasad Pandit 2025-04-17 16:07 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 3/7] migration: Add save_postcopy_prepare() savevm handler Prasad Pandit 2025-04-17 16:07 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 4/7] migration/ram: Implement save_postcopy_prepare() Prasad Pandit 2025-04-17 16:08 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 5/7] migration: enable multifd and postcopy together Prasad Pandit 2025-04-11 11:45 ` [PATCH v9 6/7] tests/qtest/migration: consolidate set capabilities Prasad Pandit 2025-04-17 16:11 ` Fabiano Rosas 2025-04-11 11:45 ` [PATCH v9 7/7] tests/qtest/migration: add postcopy tests with multifd Prasad Pandit 2025-04-17 16:10 ` Fabiano Rosas 2025-04-16 0:31 ` [PATCH v9 0/7] Allow to enable multifd and postcopy migration together Fabiano Rosas 2025-04-16 12:59 ` Fabiano Rosas 2025-04-17 11:13 ` Prasad Pandit 2025-04-17 16:05 ` Fabiano Rosas 2025-04-23 22:50 ` Peter Xu 2025-04-29 12:51 ` Prasad Pandit 2025-04-29 13:04 ` Peter Xu 2025-04-29 13:28 ` Prasad Pandit 2025-04-29 13:47 ` Peter Xu 2025-04-29 15:20 ` Prasad Pandit 2025-04-29 15:49 ` Peter Xu 2025-05-05 19:01 ` Fabiano Rosas 2025-05-06 12:32 ` Prasad Pandit 2025-05-05 19:04 ` Fabiano Rosas 2025-05-06 12:38 ` Prasad Pandit 2025-05-06 13:40 ` Fabiano Rosas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).