aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorBart Van Assche2017-04-26 15:47:48 -0500
committerJens Axboe2017-04-26 16:09:04 -0500
commit2d0364c8c1a97a1d44760895a982221c06af0f35 (patch)
tree815eee282e7f3204d4c723e5b190ffc026f0fb02 /block
parent1608fd1ca3b9357ea20ffc3a8ad2d1e4b78301a6 (diff)
downloadkernel-2d0364c8c1a97a1d44760895a982221c06af0f35.tar.gz
kernel-2d0364c8c1a97a1d44760895a982221c06af0f35.tar.xz
kernel-2d0364c8c1a97a1d44760895a982221c06af0f35.zip
blk-mq: Register <dev>/queue/mq after having registered <dev>/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 <bart.vanassche@sandisk.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-mq-sysfs.c35
-rw-r--r--block/blk-mq.h1
-rw-r--r--block/blk-sysfs.c6
3 files changed, 32 insertions, 10 deletions
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index d745ab81033a..a2dbb1a48e72 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -253,6 +253,8 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
253 struct blk_mq_hw_ctx *hctx; 253 struct blk_mq_hw_ctx *hctx;
254 int i; 254 int i;
255 255
256 lockdep_assert_held(&q->sysfs_lock);
257
256 queue_for_each_hw_ctx(q, hctx, i) 258 queue_for_each_hw_ctx(q, hctx, i)
257 blk_mq_unregister_hctx(hctx); 259 blk_mq_unregister_hctx(hctx);
258 260
@@ -267,9 +269,9 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
267 269
268void blk_mq_unregister_dev(struct device *dev, struct request_queue *q) 270void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
269{ 271{
270 blk_mq_disable_hotplug(); 272 mutex_lock(&q->sysfs_lock);
271 __blk_mq_unregister_dev(dev, q); 273 __blk_mq_unregister_dev(dev, q);
272 blk_mq_enable_hotplug(); 274 mutex_unlock(&q->sysfs_lock);
273} 275}
274 276
275void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx) 277void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx)
@@ -302,12 +304,13 @@ void blk_mq_sysfs_init(struct request_queue *q)
302 } 304 }
303} 305}
304 306
305int blk_mq_register_dev(struct device *dev, struct request_queue *q) 307int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
306{ 308{
307 struct blk_mq_hw_ctx *hctx; 309 struct blk_mq_hw_ctx *hctx;
308 int ret, i; 310 int ret, i;
309 311
310 blk_mq_disable_hotplug(); 312 WARN_ON_ONCE(!q->kobj.parent);
313 lockdep_assert_held(&q->sysfs_lock);
311 314
312 ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq"); 315 ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
313 if (ret < 0) 316 if (ret < 0)
@@ -327,8 +330,18 @@ int blk_mq_register_dev(struct device *dev, struct request_queue *q)
327 __blk_mq_unregister_dev(dev, q); 330 __blk_mq_unregister_dev(dev, q);
328 else 331 else
329 q->mq_sysfs_init_done = true; 332 q->mq_sysfs_init_done = true;
333
330out: 334out:
331 blk_mq_enable_hotplug(); 335 return ret;
336}
337
338int blk_mq_register_dev(struct device *dev, struct request_queue *q)
339{
340 int ret;
341
342 mutex_lock(&q->sysfs_lock);
343 ret = __blk_mq_register_dev(dev, q);
344 mutex_unlock(&q->sysfs_lock);
332 345
333 return ret; 346 return ret;
334} 347}
@@ -339,13 +352,17 @@ void blk_mq_sysfs_unregister(struct request_queue *q)
339 struct blk_mq_hw_ctx *hctx; 352 struct blk_mq_hw_ctx *hctx;
340 int i; 353 int i;
341 354
355 mutex_lock(&q->sysfs_lock);
342 if (!q->mq_sysfs_init_done) 356 if (!q->mq_sysfs_init_done)
343 return; 357 goto unlock;
344 358
345 blk_mq_debugfs_unregister_hctxs(q); 359 blk_mq_debugfs_unregister_hctxs(q);
346 360
347 queue_for_each_hw_ctx(q, hctx, i) 361 queue_for_each_hw_ctx(q, hctx, i)
348 blk_mq_unregister_hctx(hctx); 362 blk_mq_unregister_hctx(hctx);
363
364unlock:
365 mutex_unlock(&q->sysfs_lock);
349} 366}
350 367
351int blk_mq_sysfs_register(struct request_queue *q) 368int blk_mq_sysfs_register(struct request_queue *q)
@@ -353,8 +370,9 @@ int blk_mq_sysfs_register(struct request_queue *q)
353 struct blk_mq_hw_ctx *hctx; 370 struct blk_mq_hw_ctx *hctx;
354 int i, ret = 0; 371 int i, ret = 0;
355 372
373 mutex_lock(&q->sysfs_lock);
356 if (!q->mq_sysfs_init_done) 374 if (!q->mq_sysfs_init_done)
357 return ret; 375 goto unlock;
358 376
359 blk_mq_debugfs_register_hctxs(q); 377 blk_mq_debugfs_register_hctxs(q);
360 378
@@ -364,5 +382,8 @@ int blk_mq_sysfs_register(struct request_queue *q)
364 break; 382 break;
365 } 383 }
366 384
385unlock:
386 mutex_unlock(&q->sysfs_lock);
387
367 return ret; 388 return ret;
368} 389}
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 524f44742816..7d955c756810 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -78,6 +78,7 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q,
78 */ 78 */
79extern void blk_mq_sysfs_init(struct request_queue *q); 79extern void blk_mq_sysfs_init(struct request_queue *q);
80extern void blk_mq_sysfs_deinit(struct request_queue *q); 80extern void blk_mq_sysfs_deinit(struct request_queue *q);
81extern int __blk_mq_register_dev(struct device *dev, struct request_queue *q);
81extern int blk_mq_sysfs_register(struct request_queue *q); 82extern int blk_mq_sysfs_register(struct request_queue *q);
82extern void blk_mq_sysfs_unregister(struct request_queue *q); 83extern void blk_mq_sysfs_unregister(struct request_queue *q);
83extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx); 84extern 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 f85723332288..3f37813ccbaf 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -877,9 +877,6 @@ int blk_register_queue(struct gendisk *disk)
877 if (ret) 877 if (ret)
878 return ret; 878 return ret;
879 879
880 if (q->mq_ops)
881 blk_mq_register_dev(dev, q);
882
883 /* Prevent changes through sysfs until registration is completed. */ 880 /* Prevent changes through sysfs until registration is completed. */
884 mutex_lock(&q->sysfs_lock); 881 mutex_lock(&q->sysfs_lock);
885 882
@@ -889,6 +886,9 @@ int blk_register_queue(struct gendisk *disk)
889 goto unlock; 886 goto unlock;
890 } 887 }
891 888
889 if (q->mq_ops)
890 __blk_mq_register_dev(dev, q);
891
892 kobject_uevent(&q->kobj, KOBJ_ADD); 892 kobject_uevent(&q->kobj, KOBJ_ADD);
893 893
894 wbt_enable_default(q); 894 wbt_enable_default(q);