migration: Adjust locking in migration_maybe_pause()
In migration_maybe_pause() QEMU may yield BQL before waiting for a semaphore. However it yields the BQL too early, which logically gives it chance for the main thread to quickly take the BQL and modify the state to CANCELLING. To avoid such race condition from happening at all, always update the migration states within the BQL. It'll make sure no concurrent cancellation can ever happen. With that, IIUC there's chance we can remove the extra parameter in migration_maybe_pause() to update active state, but that'll be done separately later. Signed-off-by: Peter Xu <peterx@redhat.com> Tested-by: Jiri Denemark <jdenemar@redhat.com> Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Link: https://lore.kernel.org/r/20250114230746.3268797-9-peterx@redhat.com Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
parent
40004007e6
commit
1f9b657cae
@ -2828,14 +2828,14 @@ static int migration_maybe_pause(MigrationState *s,
|
|||||||
* wait for the 'pause_sem' semaphore.
|
* wait for the 'pause_sem' semaphore.
|
||||||
*/
|
*/
|
||||||
if (s->state != MIGRATION_STATUS_CANCELLING) {
|
if (s->state != MIGRATION_STATUS_CANCELLING) {
|
||||||
bql_unlock();
|
|
||||||
migrate_set_state(&s->state, *current_active_state,
|
migrate_set_state(&s->state, *current_active_state,
|
||||||
MIGRATION_STATUS_PRE_SWITCHOVER);
|
MIGRATION_STATUS_PRE_SWITCHOVER);
|
||||||
|
bql_unlock();
|
||||||
qemu_sem_wait(&s->pause_sem);
|
qemu_sem_wait(&s->pause_sem);
|
||||||
|
bql_lock();
|
||||||
migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER,
|
migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER,
|
||||||
new_state);
|
new_state);
|
||||||
*current_active_state = new_state;
|
*current_active_state = new_state;
|
||||||
bql_lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s->state == new_state ? 0 : -EINVAL;
|
return s->state == new_state ? 0 : -EINVAL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user