From: Yu Kuai yukuai3@huawei.com
commit 181490d5321806e537dc5386db5ea640b826bf78 upstream.
If bfq_schedule_dispatch() is called from bfq_idle_slice_timer_body(), then 'bfqd->queued' is read without holding 'bfqd->lock'. This is wrong since it can be wrote concurrently.
Fix the problem by holding 'bfqd->lock' in such case.
Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Jan Kara jack@suse.cz Reviewed-by: Chaitanya Kulkarni kch@nvidia.com Link: https://lore.kernel.org/r/20220513023507.2625717-2-yukuai3@huawei.com Signed-off-by: Jens Axboe axboe@kernel.dk Cc: Khazhy Kumykov khazhy@chromium.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- block/bfq-iosched.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -416,6 +416,8 @@ static struct bfq_io_cq *bfq_bic_lookup( */ void bfq_schedule_dispatch(struct bfq_data *bfqd) { + lockdep_assert_held(&bfqd->lock); + if (bfqd->queued != 0) { bfq_log(bfqd, "schedule dispatch"); blk_mq_run_hw_queues(bfqd->queue, true); @@ -5278,8 +5280,8 @@ bfq_idle_slice_timer_body(struct bfq_dat bfq_bfqq_expire(bfqd, bfqq, true, reason);
schedule_dispatch: - spin_unlock_irqrestore(&bfqd->lock, flags); bfq_schedule_dispatch(bfqd); + spin_unlock_irqrestore(&bfqd->lock, flags); }
/*