[2023-04-03 16:07] Greg Kroah-Hartman:
From: Chris Leech cleech@redhat.com
[ Upstream commit 00e885efcfbb8712d3e1bfc1ae30639c15ca1d3b ]
The 'q' parameter of the macro __blk_mq_run_dispatch_ops may not be one local variable, such as, it is rq->q, then request queue pointed by this variable could be changed to another queue in case of BLK_MQ_F_TAG_QUEUE_SHARED after 'dispatch_ops' returns, then 'bad unlock balance' is triggered.
Fixes the issue by adding one local variable for doing srcu lock/unlock.
Fixes: 2a904d00855f ("blk-mq: remove hctx_lock and hctx_unlock") Cc: Marco Patalano mpatalan@redhat.com Signed-off-by: Chris Leech cleech@redhat.com Signed-off-by: Ming Lei ming.lei@redhat.com Link: https://lore.kernel.org/r/20230310010913.1014789-1-ming.lei@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org
block/blk-mq.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/block/blk-mq.h b/block/blk-mq.h index ef59fee62780d..a7482d2cc82e7 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -378,12 +378,13 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, #define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \ do { \ if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) { \
int srcu_idx; \ \ might_sleep_if(check_sleep); \struct blk_mq_tag_set *__tag_set = (q)->tag_set; \
srcu_idx = srcu_read_lock((q)->tag_set->srcu); \
(dispatch_ops); \srcu_idx = srcu_read_lock(__tag_set->srcu); \
srcu_read_unlock((q)->tag_set->srcu, srcu_idx); \
} else { \ rcu_read_lock(); \ (dispatch_ops); \srcu_read_unlock(__tag_set->srcu, srcu_idx); \
On systems with their (btrfs) root filesystem residing on an LVM volume, this patch is reproducibly causing a complete freeze during shutdowns and reboots.
Regards Pascal