Files
qemu/migration
hongmianquan 96e7412cd5 migration/postcopy: fix page_requested leak for vhost-user shared pages
With postcopy-preempt enabled, a postcopy migration of a guest with a
vhost-user device can hang at the very end on the destination, after all
pages are transferred (query-migrate: status=postcopy-active, remaining=0).

Root cause is an add/del key mismatch on mis->page_requested:

- add: a backend fault goes through postcopy_request_shared_page() ->
  postcopy_request_page() -> migrate_send_rp_req_pages(), which inserts
  the request and bumps page_requested_count keyed by client_addr.
- del: qemu_ufd_copy_ioctl() removes the entry and drops the counter
  keyed by this QEMU process's host address for the page.

client_addr is a VA in the external vhost-user backend's address space and
never equals QEMU's host address, so the removal misses and the counter
leaks. postcopy_ram_incoming_cleanup() then waits for it to reach zero
forever, which also stalls the source (it waits for the return path).

Racing threads:
  dst: postcopy_ram_listen_thread -> postcopy_ram_incoming_cleanup ->
       qemu_cond_wait_impl              (waits for page_requested_count==0)
       (postcopy_preempt_thread already placed/woke the pages)
  src: migration_thread -> migration_completion ->
       await_return_path_close_on_source -> qemu_thread_join
       (source_return_path_thread blocked in recvmsg)

The leak is only triggered when the vhost-user backend faults on a page
that has not been received yet: only then does the request take the
shared-fault slow path and register an entry in page_requested. If that
page is subsequently delivered while the request is still outstanding,
its entry is never removed. (Pages already present when the backend
faults just take the wake path and never register.) So a run may leak
only a few entries (9 of ~244k requests in our repro) yet still hang.

Fix: key the request with the same host address the removal uses
(rb->host + aligned_rbo) instead of client_addr. The backend wake still
happens at placement time via postcopy_wake_shared().

Signed-off-by: hongmianquan <hongmianquan@bytedance.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
2026-08-28 09:09:32 -03:00
..
2026-05-20 15:49:10 -04:00
2026-01-17 10:46:31 +11:00
2024-12-20 17:44:56 +01:00
2026-03-09 08:53:32 -03:00
2026-03-09 08:53:32 -03:00
2026-03-09 08:53:32 -03:00
2026-03-09 08:53:32 -03:00
2025-12-27 10:11:09 +01:00
2026-08-28 09:09:31 -03:00
2026-01-23 11:32:18 -03:00
2026-01-23 11:32:18 -03:00
2025-09-02 17:57:05 +02:00
2025-09-02 17:57:05 +02:00
2026-08-28 09:09:32 -03:00