diff options
author | Bart Van Assche | 2017-04-26 15:47:48 -0500 |
---|---|---|
committer | Jens Axboe | 2017-04-26 16:09:04 -0500 |
commit | 2d0364c8c1a97a1d44760895a982221c06af0f35 (patch) | |
tree | 815eee282e7f3204d4c723e5b190ffc026f0fb02 /block | |
parent | 1608fd1ca3b9357ea20ffc3a8ad2d1e4b78301a6 (diff) | |
download | kernel-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.c | 35 | ||||
-rw-r--r-- | block/blk-mq.h | 1 | ||||
-rw-r--r-- | block/blk-sysfs.c | 6 |
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 | ||
268 | void blk_mq_unregister_dev(struct device *dev, struct request_queue *q) | 270 | void 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 | ||
275 | void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx) | 277 | void 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 | ||
305 | int blk_mq_register_dev(struct device *dev, struct request_queue *q) | 307 | int __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 | |||
330 | out: | 334 | out: |
331 | blk_mq_enable_hotplug(); | 335 | return ret; |
336 | } | ||
337 | |||
338 | int 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 | |||
364 | unlock: | ||
365 | mutex_unlock(&q->sysfs_lock); | ||
349 | } | 366 | } |
350 | 367 | ||
351 | int blk_mq_sysfs_register(struct request_queue *q) | 368 | int 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 | ||
385 | unlock: | ||
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 | */ |
79 | extern void blk_mq_sysfs_init(struct request_queue *q); | 79 | extern void blk_mq_sysfs_init(struct request_queue *q); |
80 | extern void blk_mq_sysfs_deinit(struct request_queue *q); | 80 | extern void blk_mq_sysfs_deinit(struct request_queue *q); |
81 | extern int __blk_mq_register_dev(struct device *dev, struct request_queue *q); | ||
81 | extern int blk_mq_sysfs_register(struct request_queue *q); | 82 | extern int blk_mq_sysfs_register(struct request_queue *q); |
82 | extern void blk_mq_sysfs_unregister(struct request_queue *q); | 83 | extern void blk_mq_sysfs_unregister(struct request_queue *q); |
83 | extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx); | 84 | 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 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); |