summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2018-05-14 12:17:31 -0600
committerJens Axboe <axboe@kernel.dk>2018-05-14 12:17:31 -0600
commitc854ab5773be1c1a0d3cef0c3a3261f2c48ab7f8 (patch)
treef8736038b49c548fd13327a3d2db26804f027047 /mm
parent0eb0b63c1d1a851b4c1606f4170691835d3616a2 (diff)
downloadlinux-c854ab5773be1c1a0d3cef0c3a3261f2c48ab7f8.tar.bz2
sbitmap: fix race in wait batch accounting
If we have multiple callers of sbq_wake_up(), we can end up in a situation where the wait_cnt will continually go more and more negative. Consider the case where our wake batch is 1, hence wait_cnt will start out as 1. wait_cnt == 1 CPU0 CPU1 atomic_dec_return(), cnt == 0 atomic_dec_return(), cnt == -1 cmpxchg(-1, 0) (succeeds) [wait_cnt now 0] cmpxchg(0, 1) (fails) This ends up with wait_cnt being 0, we'll wakeup immediately next time. Going through the same loop as above again, and we'll have wait_cnt -1. For the case where we have a larger wake batch, the only difference is that the starting point will be higher. We'll still end up with continually smaller batch wakeups, which defeats the purpose of the rolling wakeups. Always reset the wait_cnt to the batch value. Then it doesn't matter who wins the race. But ensure that whomever does win the race is the one that increments the ws index and wakes up our batch count, loser gets to call __sbq_wake_up() again to account his wakeups towards the next active wait state index. Fixes: 6c0ca7ae292a ("sbitmap: fix wakeup hang after sbq resize") Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'mm')
0 files changed, 0 insertions, 0 deletions