From: no-reply@sashiko.virtuozzo.com
To: svt-core@virtuozzo.com,
Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Subject: Re: [PATCH QEMU HCI-8.1 v5 25/36] vfio/migration: don't migrate device state during CPR
Date: Fri, 23 Oct 2026 17:26:42 +0000 [thread overview]
Message-ID: <010701a169ccf478-07c899c0-1d21-4c38-8528-4db80d6786ef-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261023-vfio_v1-v5-25-ba0bf3c6d122@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 for cpr-transfer source after HUP, so the gating is bypassed
- [Medium] vfio/cpr: cpr_is_in_progress() is false on the cpr-transfer source during stream
- [Medium] vfio/migration: vfio_load_state() lacks a CPR guard, so a non-empty stream re-programs MSI-X
--
commit d5eeadfa806615694344ddad118c4979064a63b2
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
vfio/migration: don't migrate device state during CPR
This patch makes the VFIO migration handlers do nothing while a CPR
migration (cpr-transfer or cpr-exec) is in progress. It gates the save,
load and VM stop/start paths 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]
Is cpr_is_in_progress() still true on the cpr-transfer source when this
runs?
On the source the predicate reduces to cpr_state_file != NULL:
migration/cpr.c:cpr_is_in_progress() {
...
return cpr_state_file != NULL;
}
For cpr-transfer, qmp_migrate() calls cpr_state_save() and only arms
cpr_transfer_add_hup_watch(). When the target closes the CPR socket:
qmp_migrate_finish_cb()
qmp_migrate_finish(addr, NULL); /* only starts an async connect */
cpr_state_close(); /* cpr_state_file = NULL */
The migration thread (vm_stop, the vmstate change notifiers,
qemu_savevm_state_setup(), vfio_save_state(), save_complete) runs only
after the connect completes. By then cpr_is_in_progress() returns false
on the source.
Would that make vfio_is_active(), vfio_save_state(),
vfio_switchover_ack_needed(), vfio_vmstate_change_prepare() and
vfio_vmstate_change() all take the normal migration path on a cpr-transfer
source? The old QEMU would then stop the live device and save its config
and state.
The target has cpr_is_incoming() true, so it skips load_setup but still
parses the stream. That looks like the vGPU breakage this patch is meant
to fix, together with a source/target mismatch.
The comment in cpr_is_in_progress() says "An outgoing CPR migration has
the CPR state open, from cpr_state_save() to cpr_state_close()", and the
commit message relies on this. Does that hold for cpr-transfer?
cpr-exec looks fine, since qmp_migrate_finish() is called directly there
and cpr_state_close() runs only on error or in migration_cleanup().
Nothing later in the series appears to change cpr_is_in_progress(),
cpr_state_save(), cpr_state_close() or qmp_migrate_finish_cb(). The later
patch "VZ: vfio/region: preserve BAR mappings across cpr-exec" adds an
mmap_blocker in vfio_device_attach() that blocks cpr-transfer for VFIO
devices. That makes the path unreachable at series end, but it doesn't
change the predicate.
[Severity: High]
Is the source-side predicate also an unlatched sample of mutable globals?
qmp_migrate_set_parameters() does not reject changing "mode" while a
migration is running. Could migrate_mode(), which cpr_is_in_progress()
reads, change between the VM stop and the later vm start or
vfio_save_state() call? The gates in vfio_vmstate_change_prepare(),
vfio_vmstate_change() and vfio_save_state() would then disagree with each
other.
[ ... ]
> @@ -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();
> +}
> +
> static const SaveVMHandlers savevm_vfio_handlers = {
> + .is_active = vfio_is_active,
> .save_prepare = vfio_save_prepare,
[Severity: Medium]
Should vfio_load_state() have a matching cpr_is_in_progress() guard?
The patch gates only the save side and load_setup (through is_active).
vfio_load_state() has no check:
hw/vfio/migration.c:vfio_load_state() {
...
case VFIO_MIG_FLAG_DEV_CONFIG_STATE:
...
return vfio_load_device_config_state(f, opaque);
}
Nothing in the loadvm section path consults is_active before calling
load_state. If the target receives a non-empty VFIO section during CPR,
it reaches vfio_pci_load_config() on the preserved device even though
vfio_load_setup() never ran. That would re-program MSI-X and disable
vector 0.
A DEV_DATA_STATE section would reach vfio_load_buffer() with data_fd == -1
and fail with EBADF, aborting the migration.
A non-empty section is reachable when the source predicate returns false,
as described above for the cpr-transfer source. The later patch "vfio/migration: don't assume
the device is running on CPR incoming" only adds cpr_is_incoming()
handling in vfio_vmstate_change() and migration init, and adds no
load-side guard.
[ ... ]
> @@ -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;
> + }
> +
[ ... ]
> @@ -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;
> + }
> +
The same cpr_is_in_progress() question applies to both of these gates on
the cpr-transfer source, since cpr_state_close() has already cleared
cpr_state_file when the VM is stopped.
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261023-vfio_v1-v5-0-ba0bf3c6d122@virtuozzo.com?part=25
next prev parent reply other threads:[~2026-10-23 17:26 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 16:53 [PATCH QEMU HCI-8.1 v5 00/36] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 01/36] VZ: migration/cpr-exec: fix Error leak in preserve_ram() Andrey Drobyshev
2026-10-23 16:58 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 02/36] migration/cpr-exec: restore RAM write access if exec fails Andrey Drobyshev
2026-10-23 16:58 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 03/36] vfio/region: create BAR dma-bufs with O_CLOEXEC Andrey Drobyshev
2026-10-23 17:00 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 04/36] migration/cpr-exec: require a file or exec migration URI Andrey Drobyshev
2026-10-23 17:00 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 05/36] migration: close the CPR state if the outgoing channel fails to open Andrey Drobyshev
2026-10-23 17:01 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 06/36] migration/cpr-exec: close the persisted state if the " Andrey Drobyshev
2026-10-23 17:01 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 07/36] migration: don't refuse a blocker over a migration of another mode Andrey Drobyshev
2026-10-23 17:03 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 08/36] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-23 17:02 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 09/36] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-23 17:04 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 10/36] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-23 17:03 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 11/36] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-23 17:04 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 12/36] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-23 17:05 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 13/36] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-23 17:05 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 14/36] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-23 17:07 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 15/36] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-23 17:06 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 16/36] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-23 17:09 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 17/36] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-10-23 17:11 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 18/36] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-23 17:13 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 19/36] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-23 17:12 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 20/36] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-23 17:12 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 21/36] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-23 17:17 ` no-reply
2026-10-23 16:53 ` [PATCH QEMU HCI-8.1 v5 22/36] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-23 17:17 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 23/36] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-23 17:19 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 24/36] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-10-23 17:19 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 25/36] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-10-23 17:26 ` no-reply [this message]
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 26/36] vfio/migration: don't assume the device is running on CPR incoming Andrey Drobyshev
2026-10-23 17:23 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 27/36] vfio/listener: skip dirty page tracking during CPR Andrey Drobyshev
2026-10-23 17:27 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 28/36] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-10-23 17:29 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 29/36] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-23 17:29 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 30/36] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-10-23 17:31 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 31/36] VZ: migration/cpr-exec: don't exec if a vhost-net device can't be released Andrey Drobyshev
2026-10-23 17:30 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 32/36] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-23 17:36 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 33/36] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-23 17:32 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 34/36] VZ: vfio/container: lift the CPR blocker for mdev " Andrey Drobyshev
2026-10-23 17:34 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 35/36] VZ: migration: keep the estimate and wait over starved windows #VSTOR-150595 Andrey Drobyshev
2026-10-23 17:38 ` no-reply
2026-10-23 16:54 ` [PATCH QEMU HCI-8.1 v5 36/36] VZ: migration: don't wait for stop-copy-only device state #VSTOR-150595 Andrey Drobyshev
2026-10-23 17:40 ` 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=010701a169ccf478-07c899c0-1d21-4c38-8528-4db80d6786ef-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.