From: Bart Van Assche Date: Wed, 26 Apr 2017 20:47:48 +0000 (-0700) Subject: blk-mq: Register /queue/mq after having registered /queue X-Git-Tag: accepted/tizen/unified/20230406.165743~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4a4595d3b13017cbd600f18b1c0ff2e2cd7082ec;p=platform%2Fkernel%2Flinux-amlogic.git blk-mq: Register /queue/mq after having registered /queue A later patch in this series will modify blk_mq_debugfs_register() such that it uses q->kobj.parent to determine the name of a request queue. Hence make sure that that pointer is initialized before blk_mq_debugfs_register() is called. To avoid lock inversion, protect sysfs / debugfs registration with the queue sysfs_lock instead of the global mutex all_q_mutex. Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Reviewed-by: Omar Sandoval Signed-off-by: Jens Axboe [sw0312.kim: backport mainline commit 2d0364c8c1a9 to fix possible deadlock in blk-mq for cpu hotplug] Signed-off-by: Seung-Woo Kim Change-Id: Id43aae4f67f6aa43b5ad0ccd19b8f40baab337b8 --- diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c index 5b64d9d7d147..1e69db2bdfcf 100644 --- a/block/blk-mq-sysfs.c +++ b/block/blk-mq-sysfs.c @@ -404,6 +404,8 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q) struct blk_mq_ctx *ctx; int i, j; + lockdep_assert_held(&q->sysfs_lock); + queue_for_each_hw_ctx(q, hctx, i) { blk_mq_unregister_hctx(hctx); @@ -424,9 +426,9 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q) void blk_mq_unregister_dev(struct device *dev, struct request_queue *q) { - blk_mq_disable_hotplug(); + mutex_lock(&q->sysfs_lock); __blk_mq_unregister_dev(dev, q); - blk_mq_enable_hotplug(); + mutex_unlock(&q->sysfs_lock); } void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx) @@ -447,12 +449,13 @@ void blk_mq_sysfs_init(struct request_queue *q) } } -int blk_mq_register_dev(struct device *dev, struct request_queue *q) +int __blk_mq_register_dev(struct device *dev, struct request_queue *q) { struct blk_mq_hw_ctx *hctx; int ret, i; - blk_mq_disable_hotplug(); + WARN_ON_ONCE(!q->kobj.parent); + lockdep_assert_held(&q->sysfs_lock); ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq"); if (ret < 0) @@ -470,8 +473,18 @@ int blk_mq_register_dev(struct device *dev, struct request_queue *q) __blk_mq_unregister_dev(dev, q); else q->mq_sysfs_init_done = true; + out: - blk_mq_enable_hotplug(); + return ret; +} + +int blk_mq_register_dev(struct device *dev, struct request_queue *q) +{ + int ret; + + mutex_lock(&q->sysfs_lock); + ret = __blk_mq_register_dev(dev, q); + mutex_unlock(&q->sysfs_lock); return ret; } @@ -482,11 +495,15 @@ void blk_mq_sysfs_unregister(struct request_queue *q) struct blk_mq_hw_ctx *hctx; int i; + mutex_lock(&q->sysfs_lock); if (!q->mq_sysfs_init_done) - return; + goto unlock; queue_for_each_hw_ctx(q, hctx, i) blk_mq_unregister_hctx(hctx); + +unlock: + mutex_unlock(&q->sysfs_lock); } int blk_mq_sysfs_register(struct request_queue *q) @@ -494,8 +511,9 @@ int blk_mq_sysfs_register(struct request_queue *q) struct blk_mq_hw_ctx *hctx; int i, ret = 0; + mutex_lock(&q->sysfs_lock); if (!q->mq_sysfs_init_done) - return ret; + goto unlock; queue_for_each_hw_ctx(q, hctx, i) { ret = blk_mq_register_hctx(hctx); @@ -503,5 +521,8 @@ int blk_mq_sysfs_register(struct request_queue *q) break; } +unlock: + mutex_unlock(&q->sysfs_lock); + return ret; } diff --git a/block/blk-mq.h b/block/blk-mq.h index c26a84d44cc4..a2cc41a984bf 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -51,6 +51,7 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, * sysfs helpers */ extern void blk_mq_sysfs_init(struct request_queue *q); +extern int __blk_mq_register_dev(struct device *dev, struct request_queue *q); extern int blk_mq_sysfs_register(struct request_queue *q); extern void blk_mq_sysfs_unregister(struct request_queue *q); extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 88c13e58c6e9..d26937ac33db 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -695,9 +695,6 @@ int blk_register_queue(struct gendisk *disk) if (ret) return ret; - if (q->mq_ops) - blk_mq_register_dev(dev, q); - /* Prevent changes through sysfs until registration is completed. */ mutex_lock(&q->sysfs_lock); @@ -707,6 +704,9 @@ int blk_register_queue(struct gendisk *disk) goto unlock; } + if (q->mq_ops) + __blk_mq_register_dev(dev, q); + kobject_uevent(&q->kobj, KOBJ_ADD); if (!q->request_fn) {