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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.