-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Potential race condition in aio_command_finish? #687
Comments
I've managed to repo the problem on a couple of aarch64 machines ( Repro steps:
After a while (almost instantly on one of my test machines, on the other it takes a few minutes), you'll see a bunch of write commands failing in dmesg and the
What's a bit confusing is even after applying the following patch to ensure that only a single thread is calling
dmesg:
and tcmu-runner.log:
This is quite odd as the |
I think |
@geordieintheshellcode This sounds reasonable and could happen IMO. Could you raise one PR to fix this ? Thanks! |
Sorry I've been quite busy recently. I will open a PR as soon as I can. Cheers |
I'd like to get a second opinion on whether there is a potential race condition in
aio_command_finish
.What does
aio_command_finish
do?On entry into the function we call
tcmur_tcmulib_cmd_complete
which locks the device'scmds_list_lock
and then callstcmulib_command_complete
to update the command ringtail
. We then unlock thecmds_list_lock
and calltcmulib_processing_complete
to notify the kernel that there are commands to reap.The Problem
We can have multiple threads calling into
aio_command_finish
concurrently. This means we can have one thread callingtcmulib_command_complete
(updating the ring buffer tail) while another thread is callingtcmulib_processing_complete
.tcmulib_processing_complete
subsequently calls intotcmu_handle_completions
on the kernel side (see target_core_user.c).As far as I can tell there is insufficient synchronisation between the user-space thread which is updating the command ring tail pointer and the kernel thread which is reading the command ring tail pointer. Our
tcmulib_command_complete
thread is essentially doing:while our kernel thread is doing:
Now, unless I'm misunderstanding something I believe that the CPU is entitled to re-order the instructions in
tcmulib_command_complete
could be re-ordered at runtime such that the increment to list->tail happens BEFORE the assignment to entry->data. In pseudo-code, something like:Whether this happens, and how likely it is to happen probably depends on the CPU architecture. If this was to occur then it would be possible for
tcmu_handle_completions
to access anentry
vialist->tail
before the store tocmd_id
has been made visible. This would result in a bogus value forcmd_id
being read and potentially the call tofind_cmd
would fail, or worse result in the wrong command being processed. TheREAD_ONCE
on the kernel side ensures thatlist->tail
is always read (rather than being read from a cached value in a register), but it DOES NOT ensure that the stores toentry
in user-space are only made visible once the increment of the tail pointer has been made visible. As far as I understand the store/load tolist->tail
should use relevant atomics or a memory barrier to ensure the correct synchronisation?I'd appreciate it if someone were to review my logic! I definitely feel like I could have missed something. I'll see if I can repro it with
tcmu-runner
.The text was updated successfully, but these errors were encountered: