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 freezed again inside rq_qos_add(), however, in this case freeze queue recursivly 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_freezed() 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 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index eb8037bae0bd..a784f6d338b4 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -724,8 +724,12 @@ void wbt_enable_default(struct gendisk *disk) if (!blk_queue_registered(q)) return; - if (queue_is_mq(q) && enable) + if (queue_is_mq(q) && enable) { + unsigned int memflags = blk_mq_freeze_queue(q); + wbt_init(disk); + blk_mq_unfreeze_queue(q, memflags); + } } EXPORT_SYMBOL_GPL(wbt_enable_default); @@ -922,7 +926,7 @@ int wbt_init(struct gendisk *disk) * 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_freezed(&rwb->rqos, disk, RQ_QOS_WBT, &wbt_rqos_ops); mutex_unlock(&q->rq_qos_mutex); if (ret) goto err_free; -- 2.51.0