diff options
author | Christoph Hellwig <hch@lst.de> | 2020-05-16 21:28:01 +0300 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2020-05-19 18:34:29 +0300 |
commit | ac7c5675fa45a372fab27d78a72d2e10e4734959 (patch) | |
tree | 7add7a513b2d64e636acf3d3912f8cf292253ad7 /drivers/md/dm.c | |
parent | 35b371ff01410ec7c73312f1c1c320de35fcfd0f (diff) | |
download | linux-ac7c5675fa45a372fab27d78a72d2e10e4734959.tar.xz |
blk-mq: allow blk_mq_make_request to consume the q_usage_counter reference
blk_mq_make_request currently needs to grab an q_usage_counter
reference when allocating a request. This is because the block layer
grabs one before calling blk_mq_make_request, but also releases it as
soon as blk_mq_make_request returns. Remove the blk_queue_exit call
after blk_mq_make_request returns, and instead let it consume the
reference. This works perfectly fine for the block layer caller, just
device mapper needs an extra reference as the old problem still
persists there. Open code blk_queue_enter_live in device mapper,
as there should be no other callers and this allows better documenting
why we do a non-try get.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8921cd79422c..f215b8666448 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1791,8 +1791,17 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio) int srcu_idx; struct dm_table *map; - if (dm_get_md_type(md) == DM_TYPE_REQUEST_BASED) + if (dm_get_md_type(md) == DM_TYPE_REQUEST_BASED) { + /* + * We are called with a live reference on q_usage_counter, but + * that one will be released as soon as we return. Grab an + * extra one as blk_mq_make_request expects to be able to + * consume a reference (which lives until the request is freed + * in case a request is allocated). + */ + percpu_ref_get(&q->q_usage_counter); return blk_mq_make_request(q, bio); + } map = dm_get_live_table(md, &srcu_idx); |