All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
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 v2 18/24] vfio/migration: don't migrate device state during CPR
Date: Tue, 13 Oct 2026 15:53:50 +0000	[thread overview]
Message-ID: <010701a135f85947-e6462840-260c-40f1-a397-427470d6640b-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261013-vfio_v1-v2-18-433455c0a294@virtuozzo.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Medium] vfio: migration save/load gated on mode parameter, not CPR in progress
- [Medium] vfio/migration: load_state not gated for CPR, unpatched source still hits live device
- [Medium] vfio/migration: switchover_ack_needed not gated for CPR, hangs migration
- [Medium] vfio/migration: stale multifd_transfer lets save thread stop device during CPR
--

commit 27c407560d6e12fc61d8fd9e47b3508c1eaa3fcb
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>

vfio/migration: don't migrate device state during CPR

This patch skips VFIO device state migration in the cpr-transfer and
cpr-exec modes. It adds a vfio_is_active() callback and an early return in
vfio_save_state(), both gated on cpr_incoming_needed(). It also makes the
VM state change handlers return early when cpr_is_in_progress().

> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
> --- a/hw/vfio/migration.c
> +++ b/hw/vfio/migration.c

[ ... ]

> @@ -674,6 +675,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_incoming_needed(NULL)) {
> +        qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
> +        return;
> +    }
> +

[Severity: Medium]
cpr_incoming_needed() only tests migrate_mode(), that is, the configured
mode parameter, and not whether a CPR operation is running.

If the mode parameter is left at cpr-transfer or cpr-exec (for example
after an earlier or failed CPR attempt) and a non-CPR save such as
snapshot-save runs, what happens?

save_snapshot()
  vm_stop(RUN_STATE_SAVE_VM)
  qemu_savevm_state()
    vfio_save_state()
      cpr_incoming_needed(NULL) is true -> only END_OF_STATE is written

In that case vfio_vmstate_change() is gated on cpr_is_in_progress(),
which requires migration_is_running() on the source, and that is false
for savevm. The device is therefore still moved to STOP, but no state is
written, so a later load restores nothing.

The commit message says the stop/cont hook uses cpr_is_in_progress()
because "the mode alone would also skip a plain stop/cont of a VM which
merely has it set". Does the same reasoning apply to vfio_save_state()
and vfio_is_active()? Should they use the same predicate as the
vmstate handlers?

[ ... ]

> @@ -824,7 +835,19 @@ static int vfio_switchover_start(void *opaque)
>      return 0;
>  }
>  
> +static bool vfio_is_active(void *opaque)
> +{
> +    return !cpr_incoming_needed(NULL);
> +}
> +
>  static const SaveVMHandlers savevm_vfio_handlers = {
> +    .is_active = vfio_is_active,
>      .save_prepare = vfio_save_prepare,
>      .save_setup = vfio_save_setup,
>      .save_cleanup = vfio_save_cleanup,

[Severity: Medium]
This isn't limited to the case above: vfio_is_active() also returns false
on the mode parameter alone, so all VFIO save handlers are disabled
whenever the mode is cpr-transfer or cpr-exec, even with no CPR handover
running.

Separately, is the load side covered? .is_active only suppresses setup,
save and pending-estimate handling, while .load_state is still called on
the destination for any section the source sends.

If the source is a QEMU without this patch, vfio_load_state() would still
see these sections:

vfio_load_state()
  case VFIO_MIG_FLAG_DEV_CONFIG_STATE:
    return vfio_load_device_config_state(f, opaque);

That would apply the config to the preserved device and re-program MSI-X,
which is the failure the commit message describes. A DATA_STATE section
would reach vfio_load_buffer()->qemu_file_get_to_fd() with data_fd still
-1, because vfio_load_setup() is skipped, and the incoming migration
would fail.

Is a version requirement on the source intended here, and should
vfio_load_state() have its own CPR check?

[Severity: Medium]
Can this hang a CPR migration when switchover-ack is enabled?

vfio_switchover_ack_needed() still returns vfio_precopy_supported() and
is not gated by is_active. On the destination,
qemu_loadvm_state_switchover_ack_needed() does:

    if (se->ops->switchover_ack_needed(se->opaque)) {
        mis->switchover_ack_pending_num++;
    }

without consulting is_active, so the VFIO device is counted as awaiting
an ACK. The fallback ACK on MIG_CMD_OPEN_RETURN_PATH then does not fire.

On the source, vfio_is_active() now returns false, so vfio_save_iterate()
is never called. That is the only place this is emitted:

    qemu_put_be64(f, VFIO_MIG_FLAG_DEV_INIT_DATA_SENT);

The destination therefore never calls qemu_loadvm_approve_switchover().
migration_can_switchover() then keeps returning s->switchover_acked
(false) while the VM is running:

    if (!runstate_is_running()) {
        return true;
    }
    return s->switchover_acked;

migrate_caps_check() only requires return-path for switchover-ack and
does not reject it in CPR modes. Should vfio_switchover_ack_needed() also
return false in CPR mode, or should the capability be rejected there?

[ ... ]

> @@ -857,6 +880,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 +910,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: Medium]
Can the multifd save thread still move the preserved device to STOP_COPY
during CPR?

qemu_savevm_state_complete_precopy_iterable() spawns
save_complete_precopy_thread for every handler that has one, without
checking .is_active. The thread's only guard is
vfio_multifd_transfer_enabled():

hw/vfio/migration-multifd.c:vfio_multifd_save_complete_precopy_thread() {
    if (!vfio_multifd_transfer_enabled(vbasedev)) {
        /* Nothing to do, vfio_save_complete_precopy() does the transfer. */
        return true;
    }
    ...
    if (vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_STOP_COPY,
                                 VFIO_DEVICE_STATE_STOP, errp)) {

migration->multifd_transfer is written only in vfio_multifd_setup(), and
vfio_multifd_cleanup() does not reset it. With this patch
vfio_save_setup() is skipped in CPR modes, so the flag is no longer
refreshed.

If an earlier non-CPR migration attempt ran vfio_save_setup() with
multifd transfer enabled and then failed or was cancelled, and a later
cpr-transfer or cpr-exec is run in the same process, would the flag still
be true and the thread stop the preserved device and stream its state?

The same flag also gates vfio_switchover_start() without an is_active
check, though that is a destination-side hook in a fresh process and is
less exposed.

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261013-vfio_v1-v2-0-433455c0a294@virtuozzo.com?part=18

  reply	other threads:[~2026-10-13 15:53 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 15:28 [PATCH QEMU HCI-8.1 v2 00/24] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 01/24] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-13 15:30   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 02/24] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-13 15:30   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 03/24] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-13 15:31   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 04/24] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-13 15:31   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 05/24] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-13 15:33   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 06/24] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-13 15:32   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 07/24] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-13 15:35   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 08/24] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-13 15:33   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 09/24] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-13 15:36   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 10/24] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-10-13 15:38   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 11/24] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-13 15:41   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 12/24] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-13 15:39   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 13/24] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-13 15:40   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 14/24] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-13 15:45   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 15/24] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-13 15:44   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 16/24] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-13 15:47   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 17/24] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-10-13 15:47   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 18/24] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-10-13 15:53   ` no-reply [this message]
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 19/24] vfio/listener: skip dirty page tracking " Andrey Drobyshev
2026-10-13 15:50   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 20/24] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-10-13 15:53   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 21/24] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-13 15:55   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 22/24] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-10-13 15:55   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 23/24] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-13 16:00   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 24/24] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-13 15:57   ` 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=010701a135f85947-e6462840-260c-40f1-a397-427470d6640b-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.