From b79fec756338eca66ef9a939f97d9dfe14472492 Mon Sep 17 00:00:00 2001 From: Jingbo Xu Date: Tue, 6 Feb 2024 10:27:12 +0800 Subject: [PATCH] anolis: blk-iocost: fix ABBA deadlock when writing blkio.cost.qos ANBZ: #8040 An ABBA deadlock is spotted when writing blkio.cost.qos to configure a block device, along with inflight IO submitted to the block device: thread 1 thread 2 -------- -------- ioc_qos_write generic_make_request generic_make_request_checks blkcg_bio_issue_check # hold ioc->lock # hold q->queue_lock blk_queue_flag_clear # request for q->queue_lock blkg_lookup_create blkg_create pol->pd_init_fn() i.e. ioc_pd_init # request for ioc->lock Along with commit 57d74df90783 ("block: use atomic bitops for ->queue_flags"), which is prior to the introduction of blk-iocost, the upstream has no this issue, since the queue flag modification doesn't need to hold queue_lock any more. As commit 57d74df90783 ("block: use atomic bitops for ->queue_flags") is introduced along with a series of cleanup after the legacy single queue mechanism is dropped, it's not recommended to cherry-pick the commit directly to the ANCK codebase. Instead, fix this issue by moving the operations of attempting to acquire q->queue_lock outside of the critical area of ioc->lock. Reported-by: Hailong liu Signed-off-by: Jingbo Xu --- block/blk-iocost.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index d6fbd75036b4..72bef02b2fbb 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2398,14 +2398,10 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, spin_lock_irq(&ioc->lock); - if (enable) { - blk_stat_enable_accounting(ioc->rqos.q); - blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, ioc->rqos.q); + if (enable) ioc->enabled = true; - } else { - blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, ioc->rqos.q); + else ioc->enabled = false; - } if (user) { memcpy(ioc->params.qos, qos, sizeof(qos)); @@ -2417,6 +2413,13 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, ioc_refresh_params(ioc, true); spin_unlock_irq(&ioc->lock); + if (enable) { + blk_stat_enable_accounting(disk->queue); + blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); + } else { + blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); + } + put_disk_and_module(disk); return nbytes; einval: -- Gitee