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 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index b1ab0f297f24..5e7e481103a1 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -725,7 +725,11 @@ void wbt_enable_default(struct gendisk *disk) return; if (queue_is_mq(q) && enable) { + unsigned int memflags = blk_mq_freeze_queue(q); + wbt_init(disk); + blk_mq_unfreeze_queue(q, memflags); + mutex_lock(&q->debugfs_mutex); blk_mq_debugfs_register_rq_qos(q); mutex_unlock(&q->debugfs_mutex); @@ -926,7 +930,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_frozen(&rwb->rqos, disk, RQ_QOS_WBT, &wbt_rqos_ops); mutex_unlock(&q->rq_qos_mutex); if (ret) goto err_free; -- 2.51.0