Conversation
This reverts commit 4fb29bc. This change is independent of the migration worker, but its code sits inside the reverted region. It is re-applied unchanged later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 705ed46. This change is independent of the migration worker, but its code sits inside the reverted region. It is re-applied unchanged later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 636637c. This change is independent of the migration worker, but its code sits inside the reverted region. It is re-applied unchanged later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit e38e586. This change is independent of the migration worker, but its code sits inside the reverted region. It is re-applied unchanged later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit d00bdc0. This change is independent of the migration worker, but its code sits inside the reverted region. It is re-applied unchanged later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit e6cd3d8. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 0582771. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit afa060f. The original subject was "vmm: Remove duplicated update_migration_progress in do_memory_iterations". This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 0b2ba9d. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 6c38ad2. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 8c86589. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. This also drops the payload from the match arm in vm_post_migration_announce(), which was added later by 0f8e073 and is therefore not part of the reverted diff. Without that the tree would not compile. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 09c6399. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 0795c73. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 0aebb7b. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 5283a0c. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit a2abcf5. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit a925363. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 806b51b. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit c70dd77. The upstream asynchronization series implements the same functionality and is cherry-picked in this series instead. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 2a2f4e6. The upstream asynchronization series implements the same functionality and is cherry-picked in this series instead. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 9fa49fd. The import lists also carry VmPostMigrationAnnounce, which stays. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 1688e55. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 838ea2e. This commit cleaned up the fork's own migration worker. Upstream's worker, which this series cherry-picks, already has the resulting shape, so the commit is not re-applied. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit fe3709f. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 23414bb. The post-migration announce call added later by 3655c61 stays. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit fbb64c8. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 9840545. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit 8bbea46. The original subject was "ch-remote: wait for migration to finish by querying migration progress". This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit d9a8206. This commit builds on the fork's own migration worker, which this series replaces with the upstream implementation. It is re-applied on top of the upstream worker later in this series. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This reverts commit cf18742. The upstream asynchronization series implements the same functionality and is cherry-picked in this series instead. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This is part of the commit series to enable live updates about an ongoing live migration. See the first commit for an introduction. This commit actually brings all the functionality together. The first version has the limitation that we populate the latest snapshot once per memory iteration, although this is the most interesting part by far. In a follow-up, we can make this more fine-grained. We guarantee that as soon as SendMigration returns, migration progress can be fetched as the underlying data source is populated. [ Adapted to the upstream migration worker: the snapshot is initialized next to the VM info snapshot in vm_send_migration() and the failure is marked next to upstream's try_resume_vm_after_failed_migration(). The fork's own worker spawn code, which this commit also touched, is gone; instead the snapshot is marked as failed when spawning the upstream worker fails, which would otherwise leave it ongoing forever. For the same reason the snapshot is installed only after the last fallible step before the hand-over, the eventfd clone. ] On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This restores the fork-only `keep_alive` option of the send-migration API call, which was dropped with the revert of commit 06a8b76 ("vmm: migration: switch to non-blocking SendMigration call"). The rest of that commit is obsolete: upstream's migration worker already dispatches the call without blocking. With `keep_alive=on` the VMM stays alive after a successful migration so that management software can fetch the final migration progress. It is then supposed to send a ShutdownVmm command. The migration progress is now marked as finished once the VMM collects the worker result, which is also where the option is evaluated. For that, the worker hands the migration configuration back to the VMM thread. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
We preserve the old behavior in ch-remote: SendMigration is blocking. A new ´--dispatch` flag however ensures that one can just dispatch the migration without waiting for it to finish (or fail). On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
`ch-remote send-migration` waits for the migration to finish again, so its exit code no longer proves that the migration was dispatched. Pass `--dispatch` to keep the dispatch semantics the test asserts on and to keep the event-monitor assertions meaningful. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
These events happen fairly often now and are very spammy in the log. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
During live migration, VM ownership is moved away from the VMM thread. To preserve guest-triggered reboot and shutdown lifecycle intent across that ownership handover, we need a small lifecycle marker to travel with the migrated VM state. This change introduces `PostMigrationLifecycleEvent` and stores it in `VmSnapshot` with `#[serde(default)]` for backward compatibility. `Vm::snapshot()` now serializes the marker, and VM construction from a snapshot restores it. No control-loop behavior is changed in this commit. This is only the data model/plumbing needed by follow-up commits. On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
While a live migration is running, the migration worker owns the VM and the VMM control loop cannot execute vm_reboot()/vmm_shutdown() directly. Guest-triggered reset/exit events in that window currently hit VmMigrating and fail. This change makes the control loop consume reset/exit as before, but when ownership is `MaybeVmOwnership::Migration` it postpones a post-migration lifecycle intent instead of calling lifecycle handlers directly. The postponed state is first-event-wins and is cleared when a new send migration starts, preventing stale lifecycle intent from leaking between migrations. This commit only introduces source-side postponing behavior and does not yet apply or replay the postponed event. [ Re-implemented on top of upstream's migration worker: the shared Arc<Mutex<Option<PostMigrationLifecycleEvent>>> is passed through MigrationWorker::spawn() instead of the fork's worker struct, the control loop matches on VmOwnership::Migration and thereby replaces upstream's two lifecycle TODO markers, and Vmm::send_migration() takes the shared state as an additional argument. The Arc/Mutex import in the worker module loses its kvm-and-x86_64 cfg, as the shared state is unconditional. ] On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
When a lifecycle event like reset or shutdown is postponed during pre-copy, switch to downtime at the next iteration boundary. This keeps the current iteration send intact and then transitions into the existing graceful downtime path (`stop_vcpu_throttling()`, `pause()`, final transfer, snapshot). To keep behavior deterministic on source migration failure, replay the postponed lifecycle event locally after ownership is returned: - VmReboot -> reset_evt - VmmShutdown -> exit_evt Postponed state is cleared on both success and failure paths to avoid stale state across migrations. [ Adapted to upstream's migration worker: the lifecycle event is replayed inside upstream's try_resume_vm_after_failed_migration(), right after it has given the VM back to the VMM. That keeps the original behaviour of replaying on every path that recovers the VM, which later also covers cancelled migrations. ] On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
[ The ownership match arm is adapted to upstream's VmOwnership enum. The todo!() in vm_cancel_migration() is filled in by the next commit, as in the original series. ] On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Introduce the minimal functionality required to support canceling a live migration. This establishes the basic mechanism, while subsequent commits will reduce the latency of cancellation so that migrations stop more promptly. Management software can and should wait for the migration to be actually canceled via the vm.migration-progress endpoint. [ Adapted to upstream's migration worker: the cancellation flag lives on MigrationWorkerHandle in migration/worker.rs and is therefore reached through VmOwnership::Migration instead of a separate Vmm field, and the cancelled VM is handed back with upstream's try_resume_vm_after_failed_migration(). ] On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This adds multiple points in the migration path where the migration can be canceled early. The pre-copy phase is not addressed here and will follow in the next commit! On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit reduces the delay in stopping memory transmission during the pre-copy phase when a migration is canceled. The cancellation handling is implemented in SendAdditionalConnections, which coordinates all memory transmission threads. In the cloud-hypervisor log, we can now even see that the cancellation happens fairly quickly when in pre-copy phase with multiple connections: ``` cloud-hypervisor: 11.263371s: <vmm> INFO:vmm/src/api/mod.rs:1147 -- API request event: VmCancelMigration () cloud-hypervisor: 11.263401s: <vmm> INFO:vmm/src/lib.rs:805 -- Will cancel ongoing live-migration cloud-hypervisor: 11.263416s: <migration> INFO:vmm/src/lib.rs:2662 -- Cancelling migration now cloud-hypervisor: 11.263568s: <migration> INFO:vmm/src/lib.rs:1667 -- Sending disconnect message to channels cloud-hypervisor: 11.263594s: <migration> INFO:vmm/src/lib.rs:1677 -- Waiting for threads to finish cloud-hypervisor: 11.302994s: <anonymous> INFO:vmm/src/lib.rs:1531 -- Sent 128 MiB via additional connection. cloud-hypervisor: 11.303037s: <anonymous> INFO:vmm/src/lib.rs:1531 -- Sent 64 MiB via additional connection. cloud-hypervisor: 11.303062s: <anonymous> INFO:vmm/src/lib.rs:1531 -- Sent 64 MiB via additional connection. cloud-hypervisor: 11.303066s: <anonymous> INFO:vmm/src/lib.rs:1531 -- Sent 64 MiB via additional connection. cloud-hypervisor: 11.303354s: <migration> INFO:vmm/src/lib.rs:1681 -- Threads finished cloud-hypervisor: 11.303672s: <migration> ERROR:vmm/src/lib.rs:858 -- migrate error: Failed to continue the migration as it was cancelled ``` On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
TL;DR: Major improvement for developers to see why a migration failed
The error model of Cloud Hypervisor leverages std::error::Error and
its source() function respectively to build chains of errors. This helps
to spot the root cause and see how a certain operation failed throughout
the stack. Therefore, the Display::fmt() impl of every error only
prints what failed "on its level", but never appends ": {0}", i.e., the
underling error's Display::fmt().
ch-remote and cloud-hypervisor can print these error chains nicely when
they exit - in the case of a migration, we do not exit however. The
solution is to print the error chain there as well to get more
meaningful errors.
As example:
old:
```
cloud-hypervisor: 62.820480s: <vmm> INFO:vmm/src/lib.rs:3382 -- VM migration check event
cloud-hypervisor: 62.820576s: <vmm> ERROR:vmm/src/lib.rs:3138 -- Migration failed: Failed to send migratable component snapshot
```
new:
```
cloud-hypervisor: 62.820480s: <vmm> INFO:vmm/src/lib.rs:3382 -- VM migration check event
cloud-hypervisor: 15.311401s: <vmm> ERROR:vmm/src/lib.rs:3110 -- Migration failed with the following chain of errors:
cloud-hypervisor: 15.311412s: <vmm> ERROR:vmm/src/lib.rs:3118 -- 0: Failed to send migratable component snapshot
cloud-hypervisor: 15.311422s: <vmm> ERROR:vmm/src/lib.rs:3118 -- 1: Error connecting to TCP socket
cloud-hypervisor: 15.311442s: <vmm> ERROR:vmm/src/lib.rs:3118 -- 2: Connection refused (os error 111)
cloud-hypervisor: 62.820618s: <vmm> INFO:event_monitor/src/lib.rs:113 -- Event: source = vm event = migration-failed
```
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Move the migration workaround from the shared Exit path to GuestExit and rename the postponed shutdown event to `VmShutdown`. With --no-shutdown, guest-triggered shutdown must keep following the guest exit path even when it is delayed until after migration completion. This preserves the distinction between guest shutdown and real VMM exit conditions. The existing fatal exit path stays unchanged. [ Adapted to upstream's migration worker: the postponement checks VmOwnership::Migration and replaces upstream's lifecycle TODO marker in the GuestExit arm of the control loop. ] On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
These are called very frequently by libvirt and spam the log. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Live migration can deadlock if the guest triggers a virtio device
activation while the migration worker owns the VM.
The failure shows up during boot and firmware, where the guest can
reset and reinitialize virtio devices while precopy is running. In the
failing case, the source log shows a pending virtio activation that
never completes:
8.115833s _virtio-pci-net_0: Needs activation; returning barrier
8.115854s vmm/src/vm.rs:464 -- Waiting for barrier
24.875452s Entering downtime phase
24.875481s stopping vcpu throttling thread
...
vCPU thread did not respond in 10ms to signal - retrying
vCPU thread did not respond in 20ms to signal - retrying
...
thread 'throttle-vcpu' (1029) panicked
...
Pause(Error signalling vCPUs: Timeout when waiting for signal
to be acknowledged)
The vCPU blocks on the activation barrier and never reaches the normal
pause checkpoint. Later, migration enters downtime and stops the vCPU
throttle thread. In the failing case, that thread is still inside a
CpuManager::pause() call, which waits for every vCPU to acknowledge
the signal. The blocked vCPU never does, so the pause times out.
The VMM already receives ActivateVirtioDevices events during
migration, but it only drains pending activations when self.vm is in
MaybeVmOwnership::Vmm. Once vm_send_migration() moves the Vm into the
migration worker, self.vm becomes MaybeVmOwnership::Migration and the
event handler no longer has a path to call activate_virtio_devices().
Fix this by storing the DeviceManager inside
MaybeVmOwnership::Migration. This keeps just enough state on the VMM
thread to drain pending virtio activations while the migration worker
owns the Vm. The barrier logic stays unchanged. The VMM now releases
the same activation barrier during migration that it already released
before migration started.
This keeps the guest from getting stuck in the activation wait and
lets the later pause succeed.
[ Re-implemented on top of upstream's migration worker: the weak device
manager reference is a field of VmOwnership::Migration instead of the
fork's MigrationVmState helper struct, and the control loop's
activation arm replaces upstream's virtio activation TODO marker. ]
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de> On-behalf-of: SAP oliver.anderson@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de> On-behalf-of: SAP oliver.anderson@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de> On-behalf-of: SAP oliver.anderson@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This will help us in libvirt/ch to distinguish short send/receive races from a real migration startup failure. By being able to check if the migration has been successfully started (rather than just the migration worker thread), we can improve the reliability of the start_migration() logic in libvirt/ch. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Streamlines the printing of the error message with upstream [0, 1]. [0] cloud-hypervisor@fcf2b5b [1] cloud-hypervisor@2527020 On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Migration threads may be left orphaned and keep the socket bound after a migration has failed. Prevent this by signaling termination via the `terminate_fd` in `ReceiveAdditionalConnections`'s `Drop` impl. On-behalf-of: SAP julian.schindel@sap.com Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
The current behavior of joining the vCPU throttling thread towards the end of a live migration is problematic when the live migration fails because then auto-converge is no longer possible on a second attempt. We fix this by instead resetting the throttling thread to its initial state. The throttling thread is now instead gracefully stopped by the ThrottleThreadHandle's destructor which runs whenever the Vm instance goes out of scope. Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de> On-behalf-of: SAP oliver.anderson@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
When a live migration fails before all memory iterations have been sent we also need to reset the throttling thread, otherwise the VM continues existing on the migration source with throttled vCPUs. Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de> On-behalf-of: SAP oliver.anderson@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
A single failing parallel migration connection can deadlock the migration sender. When the bounded send-channel is full, `SendAdditionalConnections::cleanup()` silently drops the Disconnect messages via the non-blocking `try_send`. The surviving workers drain the channel and then block forever in `recv()`, while the main thread blocks forever in `join()`. The VM stays stuck in the "migrating" state. We fix this by sending the `Disconnect` messages with a blocking send, ensuring the messages reach the migration workers. On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
When a memory-sending worker fails, the migration thread calls `SendAdditionalConnections::cleanup()`. Cleanup tries to enqueue one `Disconnect` message per worker, but the bounded channel may still contain `SendMemoryThreadMessage::Memory` values. The surviving workers currently call `send_memory_ranges()` for each such value, even though the migration has already failed. Skip that call when `worker_error` is set. This consumes the queued values without processing them and lets cleanup enqueue the `Disconnect` messages. On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de> Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
phip1611
force-pushed
the
gardenlinux-backport-asynchronization
branch
from
September 24, 2026 11:22
8fa1228 to
a562ac2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This first reverts everything building on our fork's asynchronization commit series, then applies the incompatible (and better) upstream solution and then reapplys our commits with minimal changes to make them compatible with the new base.
This is an effort to prepare the v54 bump and to test that upstream code still passes our test suite. This backport should be by far the most invasive backport.
Closes cloud-hypervisor#697.
Patchset was created with AI assistance.
libvirt pipeline: https://gitlab.cyberus-technology.de/cyberus/cloud/libvirt/-/merge_requests/294
Hints for Reviewers
Details
Branch
gardenlinux-backport-asynchronization, 83 commits on top of68e6d4ed7("hypervisor: Setfw_cfgas default feature").Structure of the series
The series has four blocks. Reading it in order is the intended way to review
it; the net diff against
68e6d4ed7is confined to 13 files and is a betterway to judge the end state.
on the fork's migration worker is reverted before the worker itself, so each
step stays compilable. The naive order (async core first) dead-ends at
034935aed; ~27 dependent commits have to go first.15cab7ee6,e03456769,5d835bdff,796fc055b,7c7a827de,a56594324,6a16b65ea.their original chronological order, plus a few align/port commits.
vm-migration/src/protocol.rs.Commit message conventions
Cherry-picked from upstream commit <sha> ("<subject>").A following paragraph names the fork-specific adaptation, if any was needed.
<component>: Reapply "<original subject>"and their body starts withThis reverts commit <revert-sha>.,i.e. they point at their own revert in block 1. An "Adapted to upstream's
migration worker: ..." paragraph explains every deviation.
(git's own default is
Reapply "<subject>", butscripts/gitlint/rulesrequires a component prefix, hence the prefixed form.)
subject verbatim.
On-behalf-of/Signed-off-bytrailers, with a secondSigned-off-byadded.Deliberately not re-applied
a904e9b9d,034935aed,e3977923b,f7303f34a,3b3eda17b,2a2f4e618,c70dd7790- the fork's async core; upstream's seriesimplements the same thing.
27ba41b55("limit to running VMs only") - upstream's worker carries theinitial VM state and resumes after a failure only if the VM was running, so
the fork-only guard is redundant. Migrating a paused source VM works
again; the revert therefore also adds the missing "don't pause twice"
guard to
do_memory_migration(), as upstream has it.838ea2e71("streamline migration failure cleanup") - upstream's workeralready has the resulting shape.
cf1874233("switch to non-blocking SendMigration call") - upstream'sworker already dispatches without blocking. Only the fork-only
keep_aliveoption survives, as the separate commit "vmm: keep the VMM alive after a
migration if requested".
Where the fork features hook into upstream's worker now
VmOwnership::Migrationgaineddevice_manager: Weak<Mutex<DeviceManager>>next to upstream's
vm_info_response, so the epoll thread keeps drainingvirtio activations. This fills upstream's
// TODO: ... virtio activation handling while migrating.MigrationWorker::spawn(); theExit/Reset/GuestExitarms of thecontrol loop fill upstream's two lifecycle
// TODOs.Arc<AtomicBool>lives onMigrationWorkerHandleand isreached through
VmOwnership::Migration, so the fork's separateVmm::migration_thread_handlefield is gone (it only existed because theflag could not be reached through the old enum).
vm_cancel_migration()ispanic-free now.
MigrationWorkerResultcarries the migration config back to the VMM thread,which is how
check_migration()evaluateskeep_alive.MIGRATION_PROGRESS_SNAPSHOT. It isinstalled after the last fallible step before the hand-over and is marked
failed when spawning the worker fails, so it can no longer stay
Ongoingforever.
Behaviour changes worth a close look
Everything below is either upstream's behaviour or follows from the decisions
above - none of it is accidental, but all of it is externally visible:
27ba41b55above).(
vm.shutdown()), which is upstream's code. It resumes device workers beforejoining them, at a point where the disk locks are already released and the
destination has taken over, and the control loop now blocks on those joins.
Upside: with
keep_alive=onthe fork used to leak the detached threads.vm.deletedevent: now emitted after the shutdown instead of before, andalso for a created-but-never-booted VM (upstream's
vm_delete).sits inside
try_resume_vm_after_failed_migration(), which is what the forkdid too (its
try_resume_vmcontained the replay); the.context()stringsstill say "after failed migration" for that reason.
vm_infoduring a migration returns the snapshot captured at dispatchtime, so
device_treeis populated andstateis the pre-migration state,instead of the fork's hardcoded
Running+device_tree: None.vm_boot/vm_restoreerror variants follow upstream (VmAlreadyCreated,VmMissingConfig), andvm_add_generic_vhost_useris no longer the fork'sunimplemented!()stub (its#[ignore]d unit test runs again).rt_sigprocmask,getcwd,clock_nanosleep) leavehttp_api_thread_rules(); they were added only for the blockingsend-migration call.
SYS_readstays.ch-remote send-migrationis unchanged: it still waits by default andpolls
vm.migration-progress, with--dispatchto opt out. Upstream's testcommit
6a16b65eaassumes fire-and-forget, so the TCP timeout test passes--dispatch(separate commit).Unchanged on purpose (safe to skip while reviewing)
vmm/src/migration_transport.rs->vmm/src/migration/transport.rsis apure rename, zero content change: keep-alive stream, TCP-thread
cancellation, worker-failure fixes, thread cleanup are all untouched.
cloud-hypervisor/src/bin/ch-remote.rs,vmm/src/vcpu_throttling.rs, theTLS stack and all of
vm-migration/except the protocol comment arebyte-identical to
68e6d4ed7.vm.deletedmoved, see above),and the wire protocol is unchanged -
Command::KeepAlive = 8/CompletePaused = 9stay, so migration between fork builds keeps working.Align/doc commits added on top of the pure revert/pick/reapply work
openapi, docs: document the migration-progress endpointvmm, openapi: document the keep_alive send-migration optionopenapi, docs: document the cancel-migration endpoint(these three sit directly after the commit that introduces the respective
surface; the endpoints were previously in neither
docs/api.mdnor theOpenAPI spec)
vm-migration: describe the discriminant collision completely- commentonly; records that upstream also uses discriminant 9 (
PageFault), whichthis branch does not need, and that fork <-> upstream migration is therefore
knowingly impossible.
Verification performed
cargo check --package cloud-hypervisoron every commit of the series(the branch is bisectable;
cargo check -p vmmalone is broken in this repobecause vmm's default features are empty).
Clippy (kvm),Clippy (mshv),Clippy (mshv+kvm),Clippy (tdx,kvm),Clippy (default features),Build (mshv),cargo clippy -p cloud-hypervisor --test integration(that file iscfg-gated, a plain check compiles it to nothing),
cargo test -p vmm --features kvm --lib(88/88),cargo +nightly fuzz checkwithRUSTFLAGS=-D warnings, and the OpenAPI validator CI uses(
openapitools/openapi-generator-cli validate).gitlintwith this repo's custom rules over all 83 commits.libvirt-testssuite were not run.The two changes most likely to show up there are the explicit source-VM
shutdown and the
vm.deletedevent order.Known open points
VmSendMigrationData::keep_aliveis the only field of that struct without#[serde(default)], so a JSON body omitting it is rejected, although theCLI syntax and the new OpenAPI entry treat it as optional. Pre-existing, not
changed here.
vm.migration-progressandvm.cancel-migrationendpoints still have noD-Bus counterpart; only the HTTP surface is documented.
fuzz/Cargo.lockis stale at the base commit already (fw_cfg fallout). CI'sfuzz job does not use
--locked, so it does not fail.Too be honest, seeing this, I am unsure if our approach is the right choice. My intuition tells me to recreate v54 directly commit by commit (or commit series by commit series) rather than investing time into the gardenlinux branch. But I am happy to stick to our plan. Just unsure if it still brings us anything. I had to revert the world to make this possible.
However, once we merged this, the other backports are far simpler.