blk_throtl_init() can be called with rq_qos_mutex held from blkcg configuration, and fs reclaim can be triggered because GFP_KERNEL is used to allocate memory. This can deadlock because rq_qos_mutex can be held with queue frozen. Fix the problem by using blkg_conf_open_bdev_frozen(), also remove useless queue frozen from blk_throtl_init(). Signed-off-by: Yu Kuai --- block/blk-throttle.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 97188a795848..6b9e76c6a24b 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1310,7 +1310,6 @@ static int blk_throtl_init(struct gendisk *disk) { struct request_queue *q = disk->queue; struct throtl_data *td; - unsigned int memflags; int ret; td = kzalloc_node(sizeof(*td), GFP_KERNEL, q->node); @@ -1319,8 +1318,6 @@ static int blk_throtl_init(struct gendisk *disk) INIT_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); throtl_service_queue_init(&td->service_queue); - - memflags = blk_mq_freeze_queue(disk->queue); blk_mq_quiesce_queue(disk->queue); q->td = td; @@ -1334,8 +1331,6 @@ static int blk_throtl_init(struct gendisk *disk) } blk_mq_unquiesce_queue(disk->queue); - blk_mq_unfreeze_queue(disk->queue, memflags); - return ret; } @@ -1345,15 +1340,18 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of, { struct blkcg *blkcg = css_to_blkcg(of_css(of)); struct blkg_conf_ctx ctx; + unsigned long memflags; struct throtl_grp *tg; - int ret; + int ret = 0; u64 v; blkg_conf_init(&ctx, buf); - ret = blkg_conf_open_bdev(&ctx); - if (ret) + memflags = blkg_conf_open_bdev_frozen(&ctx); + if (IS_ERR_VALUE(memflags)) { + ret = memflags; goto out_finish; + } if (!blk_throtl_activated(ctx.bdev->bd_queue)) { ret = blk_throtl_init(ctx.bdev->bd_disk); @@ -1382,7 +1380,7 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of, tg_conf_updated(tg, false); ret = 0; out_finish: - blkg_conf_exit(&ctx); + blkg_conf_exit_frozen(&ctx, memflags); return ret ?: nbytes; } @@ -1529,15 +1527,18 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of, { struct blkcg *blkcg = css_to_blkcg(of_css(of)); struct blkg_conf_ctx ctx; + unsigned long memflags; struct throtl_grp *tg; + int ret = 0; u64 v[4]; - int ret; blkg_conf_init(&ctx, buf); - ret = blkg_conf_open_bdev(&ctx); - if (ret) + memflags = blkg_conf_open_bdev_frozen(&ctx); + if (IS_ERR_VALUE(memflags)) { + ret = memflags; goto out_finish; + } if (!blk_throtl_activated(ctx.bdev->bd_queue)) { ret = blk_throtl_init(ctx.bdev->bd_disk); @@ -1600,7 +1601,7 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of, tg_conf_updated(tg, false); ret = 0; out_finish: - blkg_conf_exit(&ctx); + blkg_conf_exit_frozen(&ctx, memflags); return ret ?: nbytes; } -- 2.51.0