• Damien Le Moal's avatar
    block: Delay default elevator initialization · 737eb78e
    Damien Le Moal authored
    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().
    Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
    Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>