Skip to content

Commit a674153

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: split bio_queue_enter from blk_queue_enter
To prepare for fixing a gendisk shutdown race, open code the blk_queue_enter logic in bio_queue_enter. This also removes the pointless flags translation. Signed-off-by: Christoph Hellwig <hch@lst.de> Tested-by: Darrick J. Wong <djwong@kernel.org> Link: https://lore.kernel.org/r/20210929071241.934472-4-hch@lst.de Tested-by: Yi Zhang <yi.zhang@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 1f14a09 commit a674153

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

block/blk-core.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -475,18 +475,35 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
475475
static inline int bio_queue_enter(struct bio *bio)
476476
{
477477
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
478-
bool nowait = bio->bi_opf & REQ_NOWAIT;
479-
int ret;
480478

481-
ret = blk_queue_enter(q, nowait ? BLK_MQ_REQ_NOWAIT : 0);
482-
if (unlikely(ret)) {
483-
if (nowait && !blk_queue_dying(q))
479+
while (!blk_try_enter_queue(q, false)) {
480+
if (bio->bi_opf & REQ_NOWAIT) {
481+
if (blk_queue_dying(q))
482+
goto dead;
484483
bio_wouldblock_error(bio);
485-
else
486-
bio_io_error(bio);
484+
return -EBUSY;
485+
}
486+
487+
/*
488+
* read pair of barrier in blk_freeze_queue_start(), we need to
489+
* order reading __PERCPU_REF_DEAD flag of .q_usage_counter and
490+
* reading .mq_freeze_depth or queue dying flag, otherwise the
491+
* following wait may never return if the two reads are
492+
* reordered.
493+
*/
494+
smp_rmb();
495+
wait_event(q->mq_freeze_wq,
496+
(!q->mq_freeze_depth &&
497+
blk_pm_resume_queue(false, q)) ||
498+
blk_queue_dying(q));
499+
if (blk_queue_dying(q))
500+
goto dead;
487501
}
488502

489-
return ret;
503+
return 0;
504+
dead:
505+
bio_io_error(bio);
506+
return -ENODEV;
490507
}
491508

492509
void blk_queue_exit(struct request_queue *q)

0 commit comments

Comments
 (0)