summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2019-07-16 16:19:26 -0400
committerJens Axboe <axboe@kernel.dk>2019-07-18 12:20:13 -0400
commit545fbd0775bafcefc8f7bc844291bd13c44b7fdc (patch)
tree60be1aaf6d7be31cf80f44a28d53ff5b3c465487
parenta6d81d30d3cd87f85bfd922358eb18b8146c4925 (diff)
rq-qos: fix missed wake-ups in rq_qos_throttle
We saw a hang in production with WBT where there was only one waiter in the throttle path and no outstanding IO. This is because of the has_sleepers optimization that is used to make sure we don't steal an inflight counter for new submitters when there are people already on the list. We can race with our check to see if the waitqueue has any waiters (this is done locklessly) and the time we actually add ourselves to the waitqueue. If this happens we'll go to sleep and never be woken up because nobody is doing IO to wake us up. Fix this by checking if the waitqueue has a single sleeper on the list after we add ourselves, that way we have an uptodate view of the list. Reviewed-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/blk-rq-qos.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c
index 659ccb8b693f..67a0a4c07060 100644
--- a/block/blk-rq-qos.c
+++ b/block/blk-rq-qos.c
@@ -244,6 +244,7 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
244 return; 244 return;
245 245
246 prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE); 246 prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE);
247 has_sleeper = !wq_has_single_sleeper(&rqw->wait);
247 do { 248 do {
248 if (data.got_token) 249 if (data.got_token)
249 break; 250 break;