migration/multifd: Fix MultiFDSendParams.packet_num race
commit98ea497d8b8a5076be7b6ceb0dcc4a475373eb76
authorPeter Xu <peterx@redhat.com>
Fri, 2 Feb 2024 10:28:56 +0000 (2 18:28 +0800)
committerPeter Xu <peterx@redhat.com>
Mon, 5 Feb 2024 06:42:11 +0000 (5 14:42 +0800)
treea759201e668c3030f84cdaf7b73442a27e9be675
parentcde85c37ca54e4a2dbee8653181938499887f6be
migration/multifd: Fix MultiFDSendParams.packet_num race

As reported correctly by Fabiano [1] (while per Fabiano, it sourced back to
Elena's initial report in Oct 2023), MultiFDSendParams.packet_num is buggy
to be assigned and stored.  Consider two consequent operations of: (1)
queue a job into multifd send thread X, then (2) queue another sync request
to the same send thread X.  Then the MultiFDSendParams.packet_num will be
assigned twice, and the first assignment can get lost already.

To avoid that, we move the packet_num assignment from p->packet_num into
where the thread will fill in the packet.  Use atomic operations to protect
the field, making sure there's no race.

Note that atomic fetch_add() may not be good for scaling purposes, however
multifd should be fine as number of threads should normally not go beyond
16 threads.  Let's leave that concern for later but fix the issue first.

There's also a trick on how to make it always work even on 32 bit hosts for
uint64_t packet number.  Switching to uintptr_t as of now to simply the
case.  It will cause packet number to overflow easier on 32 bit, but that
shouldn't be a major concern for now as 32 bit systems is not the major
audience for any performance concerns like what multifd wants to address.

We also need to move multifd_send_state definition upper, so that
multifd_send_fill_packet() can reference it.

[1] https://lore.kernel.org/r/87o7d1jlu5.fsf@suse.de

Reported-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Link: https://lore.kernel.org/r/20240202102857.110210-23-peterx@redhat.com
Signed-off-by: Peter Xu <peterx@redhat.com>
migration/multifd.c
migration/multifd.h