memory: Fix qemu crash on starting dirty log twice with stopped VM
commita5c90c61a118027b86155cffdf4fe4e2e9de1020
authorPeter Xu <peterx@redhat.com>
Mon, 7 Feb 2022 12:30:19 +0000 (7 20:30 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 16 Feb 2022 14:01:33 +0000 (16 15:01 +0100)
treea3bf4f13d25b75abeed04e8de6e48a368e288633
parent637f1ee377eab718cb23808299ea2770e722da5c
memory: Fix qemu crash on starting dirty log twice with stopped VM

QEMU can now easily crash with two continuous migration carried out:

(qemu) migrate -d exec:cat>out
(qemu) migrate_cancel
(qemu) migrate -d exec:cat>out
[crash] ../softmmu/memory.c:2782: memory_global_dirty_log_start: Assertion
`!(global_dirty_tracking & flags)' failed.

It's because memory API provides a way to postpone dirty log stop if the VM is
stopped, and that'll be re-done until the next VM start.  It was added in 2017
with commit 1931076077 ("migration: optimize the downtime", 2017-08-01).

However the recent work on allowing dirty tracking to be bitmask broke it,
which is commit 63b41db4bc ("memory: make global_dirty_tracking a bitmask",
2021-11-01).

The fix proposed in this patch contains two things:

  (1) Instead of passing over the flags to postpone stop dirty track, we add a
      global variable (along with current vmstate_change variable) to record
      what flags to stop dirty tracking.

  (2) When start dirty tracking, instead if remove the vmstate hook directly,
      we also execute the postponed stop process so that we make sure all the
      starts and stops will be paired.

This procedure is overlooked in the bitmask-ify work in 2021.

Cc: Hyman Huang <huangy81@chinatelecom.cn>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2044818
Fixes: 63b41db4bc ("memory: make global_dirty_tracking a bitmask")
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <20220207123019.27223-1-peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
softmmu/memory.c