History

block: Delay default elevator initialization

When elevator_init_mq() is called from blk_mq_init_allocated_queue(), the only information known about the device is the number of hardware queues as the block device scan by the device driver is not completed yet for most drivers. The device type and elevator required features are not set yet, preventing to correctly select the default elevator most suitable for the device. This currently affects all multi-queue zoned block devices which default to the "none" elevator instead of the required "mq-deadline" elevator. These drives currently include host-managed SMR disks connected to a smartpqi HBA and null_blk block devices with zoned mode enabled. Upcoming NVMe Zoned Namespace devices will also be affected. Fix this by adding the boolean elevator_init argument to blk_mq_init_allocated_queue() to control the execution of elevator_init_mq(). Two cases exist: 1) elevator_init = false is used for calls to blk_mq_init_allocated_queue() within blk_mq_init_queue(). In this case, a call to elevator_init_mq() is added to __device_add_disk(), resulting in the delayed initialization of the queue elevator after the device driver finished probing the device information. This effectively allows elevator_init_mq() access to more information about the device. 2) elevator_init = true preserves the current behavior of initializing the elevator directly from blk_mq_init_allocated_queue(). This case is used for the special request based DM devices where the device gendisk is created before the queue initialization and device information (e.g. queue limits) is already known when the queue initialization is executed. Additionally, to make sure that the elevator initialization is never done while requests are in-flight (there should be none when the device driver calls device_add_disk()), freeze and quiesce the device request queue before calling blk_mq_init_sched() in elevator_init_mq().

Damien Le Moal committed 7 years ago

Commit 737eb781 parent a0958ba5 files · +28 −5Browse files

Unified · Split

5 files
  1. block/blk-mq.c +9 −3
  2. block/elevator.c +7 −0
  3. block/genhd.c +9 −0
  4. drivers/md/dm-rq.c +1 −1
  5. include/linux/blk-mq.h +2 −1
block/blk-mq.c+9−3
@@ -2695,7 +2695,11 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set) · 2694 unmodified lines
26952695 if (!uninit_q)
26962696 return ERR_PTR(-ENOMEM);
26972697
2698− q = blk_mq_init_allocated_queue(set, uninit_q);
2698+ /*
2699+ * Initialize the queue without an elevator. device_add_disk() will do
2700+ * the initialization.
2701+ */
2702+ q = blk_mq_init_allocated_queue(set, uninit_q, false);
26992703 if (IS_ERR(q))
27002704 blk_cleanup_queue(uninit_q);
27012705
@@ -2846,7 +2850,8 @@ static unsigned int nr_hw_queues(struct blk_mq_tag_set *set) · 144 unmodified lines
28462850 }
28472851
28482852 struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
2849− struct request_queue *q)
2853+ struct request_queue *q,
2854+ bool elevator_init)
28502855 {
28512856 /* mark the queue as mq asap */
28522857 q->mq_ops = set->ops;
@@ -2908,7 +2913,8 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, · 55 unmodified lines
29082913 blk_mq_add_queue_tag_set(set, q);
29092914 blk_mq_map_swqueue(q);
29102915
2911− elevator_init_mq(q);
2916+ if (elevator_init)
2917+ elevator_init_mq(q);
29122918
29132919 return q;
29142920
block/elevator.c+7−0
@@ -712,7 +712,14 @@ void elevator_init_mq(struct request_queue *q) · 711 unmodified lines
712712 if (!e)
713713 return;
714714
715+ blk_mq_freeze_queue(q);
716+ blk_mq_quiesce_queue(q);
717+
715718 err = blk_mq_init_sched(q, e);
719+
720+ blk_mq_unquiesce_queue(q);
721+ blk_mq_unfreeze_queue(q);
722+
716723 if (err) {
717724 pr_warn("\"%s\" elevator initialization failed, "
718725 "falling back to \"none\"\n", e->elevator_name);
block/genhd.c+9−0
@@ -695,6 +695,15 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, · 694 unmodified lines
695695 dev_t devt;
696696 int retval;
697697
698+ /*
699+ * The disk queue should now be all set with enough information about
700+ * the device for the elevator code to pick an adequate default
701+ * elevator if one is needed, that is, for devices requesting queue
702+ * registration.
703+ */
704+ if (register_queue)
705+ elevator_init_mq(disk->queue);
706+
698707 /* minors == 0 indicates to use ext devt from part0 and should
699708 * be accompanied with EXT_DEVT flag. Make sure all
700709 * parameters make sense.
drivers/md/dm-rq.c+1−1
@@ -563,7 +563,7 @@ int dm_mq_init_request_queue(struct mapped_device *md, struct dm_table *t) · 562 unmodified lines
563563 if (err)
564564 goto out_kfree_tag_set;
565565
566− q = blk_mq_init_allocated_queue(md->tag_set, md->queue);
566+ q = blk_mq_init_allocated_queue(md->tag_set, md->queue, true);
567567 if (IS_ERR(q)) {
568568 err = PTR_ERR(q);
569569 goto out_tag_set;
include/linux/blk-mq.h+2−1
@@ -248,7 +248,8 @@ enum { · 247 unmodified lines
248248
249249 struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *);
250250 struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
251− struct request_queue *q);
251+ struct request_queue *q,
252+ bool elevator_init);
252253 struct request_queue *blk_mq_init_sq_queue(struct blk_mq_tag_set *set,
253254 const struct blk_mq_ops *ops,
254255 unsigned int queue_depth,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t