wbt_init() can be called from sysfs attribute and wbt_enable_default(), however the lock order are inversely. - queue_wb_lat_store() freeze queue first, and then wbt_init() hold rq_qos_mutex. In this case queue will be frozen again inside rq_qos_add(), however, in this case freeze queue recursively is inoperative; - wbt_enable_default() from elevator switch will hold rq_qos_mutex first, and then rq_qos_add() will freeze queue; Fix this problem by converting to use new helper rq_qos_add_frozen() in wbt_init(), and for wbt_enable_default(), freeze queue before calling wbt_init(). Fixes: a13bd91be223 ("block/rq_qos: protect rq_qos apis with a new lock") Signed-off-by: Yu Kuai --- block/blk-wbt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index c471d11b756f..e035331a800f 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -759,7 +759,12 @@ void wbt_enable_default(struct gendisk *disk) struct rq_wb *rwb = wbt_alloc(); if (rwb) { + unsigned int memflags; + + memflags = blk_mq_freeze_queue(q); wbt_init(disk, rwb); + blk_mq_unfreeze_queue(q, memflags); + mutex_lock(&q->debugfs_mutex); blk_mq_debugfs_register_rq_qos(q); mutex_unlock(&q->debugfs_mutex); @@ -942,7 +947,7 @@ static int wbt_init(struct gendisk *disk, struct rq_wb *rwb) * Assign rwb and add the stats callback. */ mutex_lock(&q->rq_qos_mutex); - ret = rq_qos_add(&rwb->rqos, disk, RQ_QOS_WBT, &wbt_rqos_ops); + ret = rq_qos_add_frozen(&rwb->rqos, disk, RQ_QOS_WBT, &wbt_rqos_ops); mutex_unlock(&q->rq_qos_mutex); if (ret) goto err_free; -- 2.51.0