From: no-reply@sashiko.virtuozzo.com
To: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com
Subject: Re: [PATCH QEMU HCI-8.1 v3 21/28] vfio/migration: don't migrate device state during CPR
Date: Fri, 16 Oct 2026 15:55:55 +0000 [thread overview]
Message-ID: <010701a1456d5473-599ca796-a11b-4317-b61f-f922285ec6ed-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261016-vfio_v1-v3-21-47487cb5a8e5@virtuozzo.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] vfio/migration: stale cached device_state when CPR starts from a paused VM
- [Medium] vfio/migration: CPR skips VFIO state using local-only checks, breaking old-source to new-target streams
- [Medium] vfio/migration: cached device_state not synced after CPR when guest was paused
--
commit 5d90a1a10c891a1bfb1b58a35b36f468c5d28350
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
vfio/migration: don't migrate device state during CPR
This patch skips VFIO device state save and load while a CPR migration
(cpr-transfer or cpr-exec) is in progress. It gates the save, load and
VM stop/start handlers on cpr_is_in_progress(). 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]
Can the new QEMU end up with a stale cached device_state when CPR starts
from an already paused VM?
If the user stops the VM before CPR, vfio_vmstate_change(running=false)
runs while cpr_is_in_progress() is false. It moves the kernel device to
STOP and caches STOP in migration->device_state.
Once CPR starts, vfio_save_state() emits only END_OF_STATE, so no
device_state reaches the target. The new QEMU then runs
vfio_migration_init(), which does:
migration->device_state = VFIO_DEVICE_STATE_RUNNING;
It never queries the kernel. The preserved device is still in STOP.
The target stays paused, because process_incoming_migration_bh() calls
runstate_set(RUN_STATE_PAUSED) and then migration_incoming_state_destroy().
That clears the incoming mode, so cpr_is_in_progress() becomes false.
A later 'cont' then reaches vfio_vmstate_change(running=true), which
requests RUNNING. In vfio_migration_set_state() this hits:
if (new_state == migration->device_state) {
return 0;
}
No ioctl is issued, and the kernel device stays in STOP while the guest
runs. Could the cached state be synchronized with the preserved device in
this case?
The commit message says the device "is never stopped". Is that accurate
for a source that was paused before CPR?
[ ... ]
> @@ -810,6 +820,11 @@ static bool vfio_switchover_ack_needed(void *opaque)
> {
> VFIODevice *vbasedev = opaque;
>
> + /* No device state is sent during CPR, so no ACK to wait for */
> + if (cpr_is_in_progress()) {
> + return false;
> + }
> +
> return vfio_precopy_supported(vbasedev);
> }
[ ... ]
> +static bool vfio_is_active(void *opaque)
> +{
> + return !cpr_is_in_progress();
> +}
[Severity: Medium]
Is it a problem that the decision to send or load VFIO state is made only
from local runtime state?
Nothing in the stream tells the peer whether VFIO sections are present.
Consider a CPR incoming migration from a source that does not have this
patch:
vfio_is_active() returns false on the target, so loadvm_state_setup() skips
vfio_load_setup() and migration->data_fd stays -1. The old source still
sends VFIO_MIG_FLAG_DEV_DATA_STATE. vfio_load_state() has no CPR guard:
case VFIO_MIG_FLAG_DEV_DATA_STATE:
{
uint64_t data_size = qemu_get_be64(f);
if (data_size) {
ret = vfio_load_buffer(f, vbasedev, data_size);
Would that call qemu_file_get_to_fd(f, -1, size) and fail? The config
section would also still be loaded into the live device.
The reverse pair (new source, old target) looks similar. The old target
runs vfio_load_setup() and puts the live device into RESUMING. Its
vfio_switchover_ack_needed() has no CPR check, so it waits for an ACK that
the new source never sends.
docs/devel/migration/CPR.rst describes the incoming side as a new QEMU
binary, so mixed-version CPR seems to be a documented use. Is a stream flag
or a compat property needed here, or is mixed-version CPR intentionally
unsupported? I found no later patch in the series that adds a CPR guard in
vfio_load_state().
[ ... ]
> @@ -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;
> + }
> +
> if (running) {
> new_state = VFIO_DEVICE_STATE_RUNNING;
> } else {
[Severity: Medium]
Does this early return leave the cached migration->device_state out of sync
with the preserved device on the target?
On the target, vm_start() runs while the incoming mode is still set, so
this handler is skipped. For a guest paused before CPR, the kernel device
is in STOP, but vfio_migration_init() has cached RUNNING.
After the incoming migration completes, the later 'cont' calls
vfio_vmstate_change(running=true):
vfio_vmstate_change()
vfio_migration_set_state()
if (new_state == migration->device_state)
return 0;
The request is silently skipped, so the kernel device is never resumed.
Should the cache be resynchronized, or the real state queried, when the
device is inherited through CPR?
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261016-vfio_v1-v3-0-47487cb5a8e5@virtuozzo.com?part=21
next prev parent reply other threads:[~2026-10-16 15:55 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 15:25 [PATCH QEMU HCI-8.1 v3 00/28] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-16 15:25 ` [PATCH QEMU HCI-8.1 v3 01/28] VZ: migration/cpr-exec: fix Error leak in preserve_ram() Andrey Drobyshev
2026-10-16 15:28 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 02/28] migration/cpr-exec: restore RAM write access if exec fails Andrey Drobyshev
2026-10-16 15:28 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 03/28] vfio/region: create BAR dma-bufs with O_CLOEXEC Andrey Drobyshev
2026-10-16 15:30 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 04/28] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-16 15:29 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 05/28] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-16 15:30 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 06/28] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-16 15:30 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 07/28] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-16 15:31 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 08/28] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-16 15:32 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 09/28] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-16 15:31 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 10/28] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-16 15:33 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 11/28] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-16 15:32 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 12/28] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-16 15:35 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 13/28] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-10-16 15:38 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 14/28] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-16 15:41 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 15/28] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-16 15:39 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 16/28] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-16 15:40 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 17/28] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-16 15:44 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 18/28] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-16 15:44 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 19/28] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-16 15:46 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 20/28] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-10-16 15:46 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 21/28] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-10-16 15:55 ` no-reply [this message]
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 22/28] vfio/listener: skip dirty page tracking " Andrey Drobyshev
2026-10-16 15:50 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 23/28] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-10-16 15:52 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 24/28] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-16 15:55 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 25/28] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-10-16 15:58 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 26/28] VZ: migration/cpr-exec: don't exec if a vhost-net device can't be released Andrey Drobyshev
2026-10-16 15:56 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 27/28] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-16 16:02 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 28/28] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-16 15:59 ` no-reply
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=010701a1456d5473-599ca796-a11b-4317-b61f-f922285ec6ed-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.