From: no-reply@sashiko.virtuozzo.com
To: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
svt-core@virtuozzo.com
Subject: Re: [PATCH QEMU HCI-8.1 v6 25/34] vfio/migration: don't migrate device state during CPR
Date: Mon, 2 Nov 2026 11:07:27 +0000 [thread overview]
Message-ID: <010701a19bf1590f-117044d8-f3c5-4aaa-a837-e73551d5f65c-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261102-vfio_v1-v6-25-9bc7cabc850d@virtuozzo.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] vfio/migration: cpr_is_in_progress() is false on cpr-transfer source
- [High] migration: cpr_is_in_progress() is false on the cpr-transfer source
- [Medium] vfio/migration: stop/cont ignored for whole CPR outgoing window, not just the handover
--
Commit 54a8e2428cc329d383d08292ed034898e8bf828e
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
vfio/migration: don't migrate device state during CPR
This patch gates the VFIO migration handlers on cpr_is_in_progress(). With
the gates in place, device state is neither saved nor loaded during
cpr-transfer or cpr-exec, and the device state is not changed on VM
stop/start. It also resets multifd_transfer in vfio_multifd_cleanup().
> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
> --- a/hw/vfio/migration.c
> +++ b/hw/vfio/migration.c
[ ... ]
> @@ -674,6 +674,16 @@ static void vfio_save_state(QEMUFile *f, void *opaque)
> Error *local_err = NULL;
> int ret;
>
> + /*
> + * .is_active doesn't cover the non-iterable stage, so the section is
> + * still sent: leave it empty, or new QEMU would load the config into
> + * the preserved device and re-program its MSI-X.
> + */
> + if (cpr_is_in_progress()) {
> + qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
> + return;
> + }
> +
[Severity: High]
Is cpr_is_in_progress() still true here on a cpr-transfer source?
On the source it returns cpr_state_file != NULL:
migration/cpr.c:cpr_is_in_progress() {
...
return cpr_state_file != NULL;
}
For cpr-transfer, qmp_migrate() only registers a HUP watch:
qmp_migrate()
cpr_transfer_add_hup_watch(s, qmp_migrate_finish_cb, addr)
When the target closes the CPR socket, the callback runs:
qmp_migrate_finish_cb()
qmp_migrate_finish(addr, NULL);
cpr_state_close();
qmp_migrate_finish() ends up in socket_start_outgoing_migration(), which
only starts qio_channel_socket_connect_async(). The completion
(socket_outgoing_migration() -> migration_channel_connect()), the migration
thread, qemu_savevm_state_setup(), vm_stop() and vfio_save_state() all run
after the callback has returned, with cpr_state_file already NULL.
If so, cpr_is_in_progress() is false for the whole data migration on a
cpr-transfer source, and the gates in vfio_save_state(),
vfio_switchover_ack_needed(), vfio_vmstate_change_prepare() and
vfio_vmstate_change() are all bypassed. Wouldn't the device then still be
stopped and put into PRE_COPY or STOP_COPY, and its config and data state
still be sent, which is the failure the commit message describes for the
NVIDIA vGPU?
The same question applies to the source-side comment in
cpr_is_in_progress(), which says the state is open "from cpr_state_save()
to cpr_state_close()". For cpr-transfer that window ends before the data
migration starts, whereas for cpr-exec cpr_state_close() runs in
migration_cleanup() after qemu_savevm_state_cleanup().
I did not find a later patch in the series that changes cpr_is_in_progress()
or the cpr_state_close() call sites.
[ ... ]
> +/*
> + * cpr-transfer and cpr-exec hand the running device over to the new QEMU
> + * as is: its fds, mappings and interrupts are preserved and it never stops.
> + * Device state migration must stay out of it, else the device is stopped,
> + * its state saved and then resumed into the very same device.
> + */
> +static bool vfio_is_active(void *opaque)
> +{
> + return !cpr_is_in_progress();
> +}
> +
[Severity: High]
On a cpr-transfer source, wouldn't vfio_is_active() return true here, given
that cpr_state_file has already been cleared by qmp_migrate_finish_cb()?
In that case save_setup, iterate and complete would all still run for the
device.
On the target, cpr_is_in_progress() is true because the incoming mode is
set, so load_setup is skipped. vfio_load_state() has no CPR gate:
hw/vfio/migration.c:vfio_load_state() {
...
data = qemu_get_be64(f);
while (data != VFIO_MIG_FLAG_END_OF_STATE) {
...
}
Could real DEV_CONFIG_STATE or DEV_DATA_STATE sent by the source then be
loaded into the preserved live device? That would re-program MSI-X, or
write to a data_fd that was never opened. The two sides would also disagree
about whether device state is migrated.
[ ... ]
> @@ -857,6 +884,11 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running,
> Error *local_err = NULL;
> int ret;
>
> + /* The device is preserved, not a plain stop/cont: keep its state */
> + if (cpr_is_in_progress()) {
> + return;
> + }
> +
[Severity: Medium]
Can this gate skip a user-issued stop or cont while a CPR migration has been
started but the VM has not yet been stopped for handover?
On the source, cpr_state_save() sets cpr_state_file from qmp_migrate(),
before the migration thread starts. For cpr-transfer, the source then
returns to the main loop and waits for the target's HUP, with
cpr_state_file open the whole time:
qmp_migrate()
cpr_state_save()
cpr_transfer_add_hup_watch(s, qmp_migrate_finish_cb, addr)
During that window, a QMP stop or cont reaches vfio_vmstate_change_prepare()
and vfio_vmstate_change(), and both return early on cpr_is_in_progress().
The commit message says that a plain stop/cont must still change the device
state when the mode is merely set. Does that hold once CPR migration has
started but has not yet stopped the VM? A stopped guest could keep a
running, DMA-capable device, and migration->device_state would not be
updated.
The final-state series still has the source-side early return in
vfio_vmstate_change().
> @@ -882,6 +914,10 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state)
> Error *local_err = NULL;
> int ret;
>
> + if (cpr_is_in_progress()) {
> + return;
> + }
> +
[Severity: High]
Is this gate effective on a cpr-transfer source?
With cpr_state_file already cleared in qmp_migrate_finish_cb(), the early
return would not be taken when the migration thread calls vm_stop(). The
device would then still be moved to STOP or STOP_COPY, and the same applies
to vfio_save_state(), vfio_is_active() and vfio_vmstate_change_prepare().
In contrast, cpr-exec appears to work, because cpr_state_close() is called
from migration_cleanup() after qemu_savevm_state_cleanup():
migration/migration.c:migration_cleanup() {
...
qemu_savevm_state_cleanup();
cpr_state_close();
}
Should the early cpr_state_close() in qmp_migrate_finish_cb() be reconsidered,
or the predicate changed, so that cpr_is_in_progress() holds for the data
migration in cpr-transfer as well? The close in qmp_migrate_finish_cb()
seems to be the defect, rather than any mismatch between stop and start
values.
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261102-vfio_v1-v6-0-9bc7cabc850d@virtuozzo.com?part=25
next prev parent reply other threads:[~2026-11-02 11:07 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 10:36 [PATCH QEMU HCI-8.1 v6 00/34] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 01/34] VZ: migration/cpr-exec: fix Error leak in preserve_ram() Andrey Drobyshev
2026-11-02 10:39 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 02/34] migration/cpr-exec: restore RAM write access if exec fails Andrey Drobyshev
2026-11-02 10:40 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 03/34] vfio/region: create BAR dma-bufs with O_CLOEXEC Andrey Drobyshev
2026-11-02 10:40 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 04/34] migration/cpr-exec: require a file or exec migration URI Andrey Drobyshev
2026-11-02 10:42 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 05/34] migration: close the CPR state if the outgoing channel fails to open Andrey Drobyshev
2026-11-02 10:42 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 06/34] migration/cpr-exec: close the persisted state if the " Andrey Drobyshev
2026-11-02 10:44 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 07/34] migration: don't refuse a blocker over a migration of another mode Andrey Drobyshev
2026-11-02 10:44 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 08/34] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-11-02 10:44 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 09/34] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-11-02 10:45 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 10/34] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-11-02 10:45 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 11/34] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-11-02 10:45 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 12/34] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-11-02 10:46 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 13/34] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-11-02 10:46 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 14/34] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-11-02 10:48 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 15/34] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-11-02 10:47 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 16/34] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-11-02 10:51 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 17/34] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-11-02 10:51 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 18/34] migration: yank: Move register instance earlier Andrey Drobyshev
2026-11-02 10:55 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 19/34] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-11-02 10:53 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 20/34] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-11-02 10:54 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 21/34] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-11-02 10:57 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 22/34] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-11-02 11:01 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 23/34] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-11-02 11:00 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 24/34] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-11-02 11:01 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 25/34] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-11-02 11:07 ` no-reply [this message]
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 26/34] vfio/migration: don't assume the device is running on CPR incoming Andrey Drobyshev
2026-11-02 11:06 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 27/34] migration/ram: don't start dirty logging in CPR modes Andrey Drobyshev
2026-11-02 11:07 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 28/34] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-11-02 11:09 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 29/34] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-11-02 11:09 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 30/34] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-11-02 11:11 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 31/34] VZ: migration/cpr-exec: don't exec if a vhost-net device can't be released Andrey Drobyshev
2026-11-02 11:10 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 32/34] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-11-02 11:16 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 33/34] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-11-02 11:12 ` no-reply
2026-11-02 10:36 ` [PATCH QEMU HCI-8.1 v6 34/34] VZ: vfio/migration: don't wait for stop-copy-only device state #VSTOR-141821 Andrey Drobyshev
2026-11-02 11:15 ` no-reply
-- strict thread matches above, loose matches on Subject: below --
2026-10-30 14:45 [PATCH QEMU HCI-8.1 v6 00/34] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-30 14:45 ` [PATCH QEMU HCI-8.1 v6 25/34] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=010701a19bf1590f-117044d8-f3c5-4aaa-a837-e73551d5f65c-000000@eu-central-1.amazonses.com \
--to=no-reply@sashiko.virtuozzo.com \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox