lkml.org 
[lkml]   [2022]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH -next 4/4] blk-cgroup: synchronize del_gendisk() with configuring cgroup policy
Date
From: Yu Kuai <yukuai3@huawei.com>

iocost is initialized when it's configured the first time, and iocost
initializing can race with del_gendisk(), which will cause null pointer
dereference:

t1 t2
ioc_qos_write
blk_iocost_init
rq_qos_add
del_gendisk
rq_qos_exit
//iocost is removed from q->roqs
blkcg_activate_policy
pd_init_fn
ioc_pd_init
ioc = q_to_ioc(blkg->q)
//can't find iocost and return null

Fix the problem by adding a new mutex in request_queue, and use it to
synchronize rq_qos_exit() from del_gendisk() with configuring cgroup
policy.

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
block/blk-cgroup.c | 3 +++
block/blk-rq-qos.c | 8 ++++++++
include/linux/blkdev.h | 1 +
3 files changed, 12 insertions(+)

diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index ad612148cf3b..8dcdaacb52a1 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -658,12 +658,14 @@ struct block_device *blkcg_conf_open_bdev(char **inputp)
return ERR_PTR(-ENODEV);
}

+ mutex_lock(&bdev->bd_queue->blkcg_pols_lock);
*inputp = input;
return bdev;
}

void blkcg_conf_close_bdev(struct block_device *bdev)
{
+ mutex_unlock(&bdev->bd_queue->blkcg_pols_lock);
blkdev_put_no_open(bdev);
}

@@ -1277,6 +1279,7 @@ int blkcg_init_disk(struct gendisk *disk)
int ret;

INIT_LIST_HEAD(&q->blkg_list);
+ mutex_init(&q->blkcg_pols_lock);

new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL);
if (!new_blkg)
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c
index efffc6fa55db..86bccdfa1a43 100644
--- a/block/blk-rq-qos.c
+++ b/block/blk-rq-qos.c
@@ -290,6 +290,10 @@ void rq_qos_exit(struct request_queue *q)
{
struct rq_qos *rqos;

+#ifdef CONFIG_BLK_CGROUP
+ mutex_lock(&q->blkcg_pols_lock);
+#endif
+
spin_lock_irq(&q->queue_lock);
rqos = q->rq_qos;
q->rq_qos = NULL;
@@ -300,4 +304,8 @@ void rq_qos_exit(struct request_queue *q)
rqos->ops->exit(rqos);
rqos = rqos->next;
} while (rqos);
+
+#ifdef CONFIG_BLK_CGROUP
+ mutex_unlock(&q->blkcg_pols_lock);
+#endif
}
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 301cf1cf4f2f..824d68a41a83 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -484,6 +484,7 @@ struct request_queue {
DECLARE_BITMAP (blkcg_pols, BLKCG_MAX_POLS);
struct blkcg_gq *root_blkg;
struct list_head blkg_list;
+ struct mutex blkcg_pols_lock;
#endif

struct queue_limits limits;
--
2.31.1
\
 
 \ /
  Last update: 2022-12-17 03:49    [W:0.067 / U:3.312 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site