Commit 09df6a75 authored by Jan Kara's avatar Jan Kara Committed by Jens Axboe

bfq: Fix warning in bfqq_request_over_limit()

People are occasionally reporting a warning bfqq_request_over_limit()
triggering reporting that BFQ's idea of cgroup hierarchy (and its depth)
does not match what generic blkcg code thinks. This can actually happen
when bfqq gets moved between BFQ groups while bfqq_request_over_limit()
is running. Make sure the code is safe against BFQ queue being moved to
a different BFQ group.

Fixes: 76f1df88 ("bfq: Limit number of requests consumed by each cgroup")
CC: stable@vger.kernel.org
Link: https://lore.kernel.org/all/CAJCQCtTw_2C7ZSz7as5Gvq=OmnDiio=HRkQekqWpKot84sQhFA@mail.gmail.com/Reported-by: default avatarChris Murphy <lists@colorremedies.com>
Reported-by: default avatar"yukuai (C)" <yukuai3@huawei.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20220407140738.9723-1-jack@suse.czSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 4cddeaca
...@@ -569,7 +569,7 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit) ...@@ -569,7 +569,7 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
struct bfq_entity *entity = &bfqq->entity; struct bfq_entity *entity = &bfqq->entity;
struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH]; struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH];
struct bfq_entity **entities = inline_entities; struct bfq_entity **entities = inline_entities;
int depth, level; int depth, level, alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
int class_idx = bfqq->ioprio_class - 1; int class_idx = bfqq->ioprio_class - 1;
struct bfq_sched_data *sched_data; struct bfq_sched_data *sched_data;
unsigned long wsum; unsigned long wsum;
...@@ -578,15 +578,21 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit) ...@@ -578,15 +578,21 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
if (!entity->on_st_or_in_serv) if (!entity->on_st_or_in_serv)
return false; return false;
retry:
spin_lock_irq(&bfqd->lock);
/* +1 for bfqq entity, root cgroup not included */ /* +1 for bfqq entity, root cgroup not included */
depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1; depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1;
if (depth > BFQ_LIMIT_INLINE_DEPTH) { if (depth > alloc_depth) {
spin_unlock_irq(&bfqd->lock);
if (entities != inline_entities)
kfree(entities);
entities = kmalloc_array(depth, sizeof(*entities), GFP_NOIO); entities = kmalloc_array(depth, sizeof(*entities), GFP_NOIO);
if (!entities) if (!entities)
return false; return false;
alloc_depth = depth;
goto retry;
} }
spin_lock_irq(&bfqd->lock);
sched_data = entity->sched_data; sched_data = entity->sched_data;
/* Gather our ancestors as we need to traverse them in reverse order */ /* Gather our ancestors as we need to traverse them in reverse order */
level = 0; level = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment