Skip to content

Commit d432c81

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: don't update BLK_FEAT_POLL in __blk_mq_update_nr_hw_queues
When __blk_mq_update_nr_hw_queues changes the number of tag sets, it might have to disable poll queues. Currently it does so by adjusting the BLK_FEAT_POLL, which is a bit against the intent of features that describe hardware / driver capabilities, but more importantly causes nasty lock order problems with the broadly held freeze when updating the number of hardware queues and the limits lock. Fix this by leaving BLK_FEAT_POLL alone, and instead check for the number of poll queues in the bio submission and poll handlers. While this adds extra work to the fast path, the variables are in cache lines used by these operations anyway, so it should be cheap enough. Fixes: 8023e14 ("block: move the poll flag to queue_limits") Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Ming Lei <[email protected]> Reviewed-by: Damien Le Moal <[email protected]> Reviewed-by: Martin K. Petersen <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Reviewed-by: Nilay Shroff <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 958148a commit d432c81

File tree

4 files changed

+22
-26
lines changed

4 files changed

+22
-26
lines changed

block/blk-core.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -951,14 +951,13 @@ int bio_poll(struct bio *bio, struct io_comp_batch *iob, unsigned int flags)
951951
*/
952952
if (!percpu_ref_tryget(&q->q_usage_counter))
953953
return 0;
954-
if (!(q->limits.features & BLK_FEAT_POLL)) {
955-
ret = 0;
956-
} else if (queue_is_mq(q)) {
954+
if (queue_is_mq(q)) {
957955
ret = blk_mq_poll(q, cookie, iob, flags);
958956
} else {
959957
struct gendisk *disk = q->disk;
960958

961-
if (disk && disk->fops->poll_bio)
959+
if ((q->limits.features & BLK_FEAT_POLL) && disk &&
960+
disk->fops->poll_bio)
962961
ret = disk->fops->poll_bio(bio, iob, flags);
963962
}
964963
blk_queue_exit(q);

block/blk-mq.c

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,8 +3105,7 @@ void blk_mq_submit_bio(struct bio *bio)
31053105
goto queue_exit;
31063106
}
31073107

3108-
if ((bio->bi_opf & REQ_POLLED) &&
3109-
!(q->limits.features & BLK_FEAT_POLL)) {
3108+
if ((bio->bi_opf & REQ_POLLED) && !blk_mq_can_poll(q)) {
31103109
bio->bi_status = BLK_STS_NOTSUPP;
31113110
bio_endio(bio);
31123111
goto queue_exit;
@@ -4328,12 +4327,6 @@ void blk_mq_release(struct request_queue *q)
43284327
blk_mq_sysfs_deinit(q);
43294328
}
43304329

4331-
static bool blk_mq_can_poll(struct blk_mq_tag_set *set)
4332-
{
4333-
return set->nr_maps > HCTX_TYPE_POLL &&
4334-
set->map[HCTX_TYPE_POLL].nr_queues;
4335-
}
4336-
43374330
struct request_queue *blk_mq_alloc_queue(struct blk_mq_tag_set *set,
43384331
struct queue_limits *lim, void *queuedata)
43394332
{
@@ -4344,7 +4337,7 @@ struct request_queue *blk_mq_alloc_queue(struct blk_mq_tag_set *set,
43444337
if (!lim)
43454338
lim = &default_lim;
43464339
lim->features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT;
4347-
if (blk_mq_can_poll(set))
4340+
if (set->nr_maps > HCTX_TYPE_POLL)
43484341
lim->features |= BLK_FEAT_POLL;
43494342

43504343
q = blk_alloc_queue(lim, set->numa_node);
@@ -5032,8 +5025,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50325025
fallback:
50335026
blk_mq_update_queue_map(set);
50345027
list_for_each_entry(q, &set->tag_list, tag_set_list) {
5035-
struct queue_limits lim;
5036-
50375028
blk_mq_realloc_hw_ctxs(set, q);
50385029

50395030
if (q->nr_hw_queues != set->nr_hw_queues) {
@@ -5047,13 +5038,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50475038
set->nr_hw_queues = prev_nr_hw_queues;
50485039
goto fallback;
50495040
}
5050-
lim = queue_limits_start_update(q);
5051-
if (blk_mq_can_poll(set))
5052-
lim.features |= BLK_FEAT_POLL;
5053-
else
5054-
lim.features &= ~BLK_FEAT_POLL;
5055-
if (queue_limits_commit_update(q, &lim) < 0)
5056-
pr_warn("updating the poll flag failed\n");
50575041
blk_mq_map_swqueue(q);
50585042
}
50595043

@@ -5113,9 +5097,9 @@ static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
51135097
int blk_mq_poll(struct request_queue *q, blk_qc_t cookie,
51145098
struct io_comp_batch *iob, unsigned int flags)
51155099
{
5116-
struct blk_mq_hw_ctx *hctx = xa_load(&q->hctx_table, cookie);
5117-
5118-
return blk_hctx_poll(q, hctx, iob, flags);
5100+
if (!blk_mq_can_poll(q))
5101+
return 0;
5102+
return blk_hctx_poll(q, xa_load(&q->hctx_table, cookie), iob, flags);
51195103
}
51205104

51215105
int blk_rq_poll(struct request *rq, struct io_comp_batch *iob,

block/blk-mq.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,4 +448,10 @@ do { \
448448
#define blk_mq_run_dispatch_ops(q, dispatch_ops) \
449449
__blk_mq_run_dispatch_ops(q, true, dispatch_ops) \
450450

451+
static inline bool blk_mq_can_poll(struct request_queue *q)
452+
{
453+
return (q->limits.features & BLK_FEAT_POLL) &&
454+
q->tag_set->map[HCTX_TYPE_POLL].nr_queues;
455+
}
456+
451457
#endif

block/blk-sysfs.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,17 @@ static ssize_t queue_##_name##_show(struct gendisk *disk, char *page) \
245245
!!(disk->queue->limits.features & _feature)); \
246246
}
247247

248-
QUEUE_SYSFS_FEATURE_SHOW(poll, BLK_FEAT_POLL);
249248
QUEUE_SYSFS_FEATURE_SHOW(fua, BLK_FEAT_FUA);
250249
QUEUE_SYSFS_FEATURE_SHOW(dax, BLK_FEAT_DAX);
251250

251+
static ssize_t queue_poll_show(struct gendisk *disk, char *page)
252+
{
253+
if (queue_is_mq(disk->queue))
254+
return sysfs_emit(page, "%u\n", blk_mq_can_poll(disk->queue));
255+
return sysfs_emit(page, "%u\n",
256+
!!(disk->queue->limits.features & BLK_FEAT_POLL));
257+
}
258+
252259
static ssize_t queue_zoned_show(struct gendisk *disk, char *page)
253260
{
254261
if (blk_queue_is_zoned(disk->queue))

0 commit comments

Comments
 (0)