162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2016 Red Hat, Inc. All rights reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file is released under the GPL. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "dm-core.h" 962306a36Sopenharmony_ci#include "dm-rq.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/blk-mq.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define DM_MSG_PREFIX "core-rq" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* 1662306a36Sopenharmony_ci * One of these is allocated per request. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_cistruct dm_rq_target_io { 1962306a36Sopenharmony_ci struct mapped_device *md; 2062306a36Sopenharmony_ci struct dm_target *ti; 2162306a36Sopenharmony_ci struct request *orig, *clone; 2262306a36Sopenharmony_ci struct kthread_work work; 2362306a36Sopenharmony_ci blk_status_t error; 2462306a36Sopenharmony_ci union map_info info; 2562306a36Sopenharmony_ci struct dm_stats_aux stats_aux; 2662306a36Sopenharmony_ci unsigned long duration_jiffies; 2762306a36Sopenharmony_ci unsigned int n_sectors; 2862306a36Sopenharmony_ci unsigned int completed; 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define DM_MQ_NR_HW_QUEUES 1 3262306a36Sopenharmony_ci#define DM_MQ_QUEUE_DEPTH 2048 3362306a36Sopenharmony_cistatic unsigned int dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES; 3462306a36Sopenharmony_cistatic unsigned int dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * Request-based DM's mempools' reserved IOs set by the user. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci#define RESERVED_REQUEST_BASED_IOS 256 4062306a36Sopenharmony_cistatic unsigned int reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciunsigned int dm_get_reserved_rq_based_ios(void) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci return __dm_get_module_param(&reserved_rq_based_ios, 4562306a36Sopenharmony_ci RESERVED_REQUEST_BASED_IOS, DM_RESERVED_MAX_IOS); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic unsigned int dm_get_blk_mq_nr_hw_queues(void) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci return __dm_get_module_param(&dm_mq_nr_hw_queues, 1, 32); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic unsigned int dm_get_blk_mq_queue_depth(void) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci return __dm_get_module_param(&dm_mq_queue_depth, 5662306a36Sopenharmony_ci DM_MQ_QUEUE_DEPTH, BLK_MQ_MAX_DEPTH); 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciint dm_request_based(struct mapped_device *md) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci return queue_is_mq(md->queue); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_civoid dm_start_queue(struct request_queue *q) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci blk_mq_unquiesce_queue(q); 6762306a36Sopenharmony_ci blk_mq_kick_requeue_list(q); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_civoid dm_stop_queue(struct request_queue *q) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci blk_mq_quiesce_queue(q); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* 7662306a36Sopenharmony_ci * Partial completion handling for request-based dm 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_cistatic void end_clone_bio(struct bio *clone) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct dm_rq_clone_bio_info *info = 8162306a36Sopenharmony_ci container_of(clone, struct dm_rq_clone_bio_info, clone); 8262306a36Sopenharmony_ci struct dm_rq_target_io *tio = info->tio; 8362306a36Sopenharmony_ci unsigned int nr_bytes = info->orig->bi_iter.bi_size; 8462306a36Sopenharmony_ci blk_status_t error = clone->bi_status; 8562306a36Sopenharmony_ci bool is_last = !clone->bi_next; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci bio_put(clone); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (tio->error) 9062306a36Sopenharmony_ci /* 9162306a36Sopenharmony_ci * An error has already been detected on the request. 9262306a36Sopenharmony_ci * Once error occurred, just let clone->end_io() handle 9362306a36Sopenharmony_ci * the remainder. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci return; 9662306a36Sopenharmony_ci else if (error) { 9762306a36Sopenharmony_ci /* 9862306a36Sopenharmony_ci * Don't notice the error to the upper layer yet. 9962306a36Sopenharmony_ci * The error handling decision is made by the target driver, 10062306a36Sopenharmony_ci * when the request is completed. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci tio->error = error; 10362306a36Sopenharmony_ci goto exit; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* 10762306a36Sopenharmony_ci * I/O for the bio successfully completed. 10862306a36Sopenharmony_ci * Notice the data completion to the upper layer. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ci tio->completed += nr_bytes; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* 11362306a36Sopenharmony_ci * Update the original request. 11462306a36Sopenharmony_ci * Do not use blk_mq_end_request() here, because it may complete 11562306a36Sopenharmony_ci * the original request before the clone, and break the ordering. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci if (is_last) 11862306a36Sopenharmony_ci exit: 11962306a36Sopenharmony_ci blk_update_request(tio->orig, BLK_STS_OK, tio->completed); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic struct dm_rq_target_io *tio_from_request(struct request *rq) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci return blk_mq_rq_to_pdu(rq); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic void rq_end_stats(struct mapped_device *md, struct request *orig) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci if (unlikely(dm_stats_used(&md->stats))) { 13062306a36Sopenharmony_ci struct dm_rq_target_io *tio = tio_from_request(orig); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci tio->duration_jiffies = jiffies - tio->duration_jiffies; 13362306a36Sopenharmony_ci dm_stats_account_io(&md->stats, rq_data_dir(orig), 13462306a36Sopenharmony_ci blk_rq_pos(orig), tio->n_sectors, true, 13562306a36Sopenharmony_ci tio->duration_jiffies, &tio->stats_aux); 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci/* 14062306a36Sopenharmony_ci * Don't touch any member of the md after calling this function because 14162306a36Sopenharmony_ci * the md may be freed in dm_put() at the end of this function. 14262306a36Sopenharmony_ci * Or do dm_get() before calling this function and dm_put() later. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_cistatic void rq_completed(struct mapped_device *md) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * dm_put() must be at the end of this function. See the comment above 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_ci dm_put(md); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* 15362306a36Sopenharmony_ci * Complete the clone and the original request. 15462306a36Sopenharmony_ci * Must be called without clone's queue lock held, 15562306a36Sopenharmony_ci * see end_clone_request() for more details. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_cistatic void dm_end_request(struct request *clone, blk_status_t error) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct dm_rq_target_io *tio = clone->end_io_data; 16062306a36Sopenharmony_ci struct mapped_device *md = tio->md; 16162306a36Sopenharmony_ci struct request *rq = tio->orig; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci blk_rq_unprep_clone(clone); 16462306a36Sopenharmony_ci tio->ti->type->release_clone_rq(clone, NULL); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci rq_end_stats(md, rq); 16762306a36Sopenharmony_ci blk_mq_end_request(rq, error); 16862306a36Sopenharmony_ci rq_completed(md); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic void __dm_mq_kick_requeue_list(struct request_queue *q, unsigned long msecs) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci blk_mq_delay_kick_requeue_list(q, msecs); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_civoid dm_mq_kick_requeue_list(struct mapped_device *md) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci __dm_mq_kick_requeue_list(md->queue, 0); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ciEXPORT_SYMBOL(dm_mq_kick_requeue_list); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic void dm_mq_delay_requeue_request(struct request *rq, unsigned long msecs) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci blk_mq_requeue_request(rq, false); 18562306a36Sopenharmony_ci __dm_mq_kick_requeue_list(rq->q, msecs); 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic void dm_requeue_original_request(struct dm_rq_target_io *tio, bool delay_requeue) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct mapped_device *md = tio->md; 19162306a36Sopenharmony_ci struct request *rq = tio->orig; 19262306a36Sopenharmony_ci unsigned long delay_ms = delay_requeue ? 100 : 0; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci rq_end_stats(md, rq); 19562306a36Sopenharmony_ci if (tio->clone) { 19662306a36Sopenharmony_ci blk_rq_unprep_clone(tio->clone); 19762306a36Sopenharmony_ci tio->ti->type->release_clone_rq(tio->clone, NULL); 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci dm_mq_delay_requeue_request(rq, delay_ms); 20162306a36Sopenharmony_ci rq_completed(md); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic void dm_done(struct request *clone, blk_status_t error, bool mapped) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci int r = DM_ENDIO_DONE; 20762306a36Sopenharmony_ci struct dm_rq_target_io *tio = clone->end_io_data; 20862306a36Sopenharmony_ci dm_request_endio_fn rq_end_io = NULL; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (tio->ti) { 21162306a36Sopenharmony_ci rq_end_io = tio->ti->type->rq_end_io; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (mapped && rq_end_io) 21462306a36Sopenharmony_ci r = rq_end_io(tio->ti, clone, error, &tio->info); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (unlikely(error == BLK_STS_TARGET)) { 21862306a36Sopenharmony_ci if (req_op(clone) == REQ_OP_DISCARD && 21962306a36Sopenharmony_ci !clone->q->limits.max_discard_sectors) 22062306a36Sopenharmony_ci disable_discard(tio->md); 22162306a36Sopenharmony_ci else if (req_op(clone) == REQ_OP_WRITE_ZEROES && 22262306a36Sopenharmony_ci !clone->q->limits.max_write_zeroes_sectors) 22362306a36Sopenharmony_ci disable_write_zeroes(tio->md); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci switch (r) { 22762306a36Sopenharmony_ci case DM_ENDIO_DONE: 22862306a36Sopenharmony_ci /* The target wants to complete the I/O */ 22962306a36Sopenharmony_ci dm_end_request(clone, error); 23062306a36Sopenharmony_ci break; 23162306a36Sopenharmony_ci case DM_ENDIO_INCOMPLETE: 23262306a36Sopenharmony_ci /* The target will handle the I/O */ 23362306a36Sopenharmony_ci return; 23462306a36Sopenharmony_ci case DM_ENDIO_REQUEUE: 23562306a36Sopenharmony_ci /* The target wants to requeue the I/O */ 23662306a36Sopenharmony_ci dm_requeue_original_request(tio, false); 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci case DM_ENDIO_DELAY_REQUEUE: 23962306a36Sopenharmony_ci /* The target wants to requeue the I/O after a delay */ 24062306a36Sopenharmony_ci dm_requeue_original_request(tio, true); 24162306a36Sopenharmony_ci break; 24262306a36Sopenharmony_ci default: 24362306a36Sopenharmony_ci DMCRIT("unimplemented target endio return value: %d", r); 24462306a36Sopenharmony_ci BUG(); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/* 24962306a36Sopenharmony_ci * Request completion handler for request-based dm 25062306a36Sopenharmony_ci */ 25162306a36Sopenharmony_cistatic void dm_softirq_done(struct request *rq) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci bool mapped = true; 25462306a36Sopenharmony_ci struct dm_rq_target_io *tio = tio_from_request(rq); 25562306a36Sopenharmony_ci struct request *clone = tio->clone; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (!clone) { 25862306a36Sopenharmony_ci struct mapped_device *md = tio->md; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci rq_end_stats(md, rq); 26162306a36Sopenharmony_ci blk_mq_end_request(rq, tio->error); 26262306a36Sopenharmony_ci rq_completed(md); 26362306a36Sopenharmony_ci return; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (rq->rq_flags & RQF_FAILED) 26762306a36Sopenharmony_ci mapped = false; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci dm_done(clone, tio->error, mapped); 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci/* 27362306a36Sopenharmony_ci * Complete the clone and the original request with the error status 27462306a36Sopenharmony_ci * through softirq context. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_cistatic void dm_complete_request(struct request *rq, blk_status_t error) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct dm_rq_target_io *tio = tio_from_request(rq); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci tio->error = error; 28162306a36Sopenharmony_ci if (likely(!blk_should_fake_timeout(rq->q))) 28262306a36Sopenharmony_ci blk_mq_complete_request(rq); 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* 28662306a36Sopenharmony_ci * Complete the not-mapped clone and the original request with the error status 28762306a36Sopenharmony_ci * through softirq context. 28862306a36Sopenharmony_ci * Target's rq_end_io() function isn't called. 28962306a36Sopenharmony_ci * This may be used when the target's clone_and_map_rq() function fails. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_cistatic void dm_kill_unmapped_request(struct request *rq, blk_status_t error) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci rq->rq_flags |= RQF_FAILED; 29462306a36Sopenharmony_ci dm_complete_request(rq, error); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic enum rq_end_io_ret end_clone_request(struct request *clone, 29862306a36Sopenharmony_ci blk_status_t error) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct dm_rq_target_io *tio = clone->end_io_data; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci dm_complete_request(tio->orig, error); 30362306a36Sopenharmony_ci return RQ_END_IO_NONE; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig, 30762306a36Sopenharmony_ci void *data) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct dm_rq_target_io *tio = data; 31062306a36Sopenharmony_ci struct dm_rq_clone_bio_info *info = 31162306a36Sopenharmony_ci container_of(bio, struct dm_rq_clone_bio_info, clone); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci info->orig = bio_orig; 31462306a36Sopenharmony_ci info->tio = tio; 31562306a36Sopenharmony_ci bio->bi_end_io = end_clone_bio; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci return 0; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic int setup_clone(struct request *clone, struct request *rq, 32162306a36Sopenharmony_ci struct dm_rq_target_io *tio, gfp_t gfp_mask) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci int r; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci r = blk_rq_prep_clone(clone, rq, &tio->md->mempools->bs, gfp_mask, 32662306a36Sopenharmony_ci dm_rq_bio_constructor, tio); 32762306a36Sopenharmony_ci if (r) 32862306a36Sopenharmony_ci return r; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci clone->end_io = end_clone_request; 33162306a36Sopenharmony_ci clone->end_io_data = tio; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci tio->clone = clone; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic void init_tio(struct dm_rq_target_io *tio, struct request *rq, 33962306a36Sopenharmony_ci struct mapped_device *md) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci tio->md = md; 34262306a36Sopenharmony_ci tio->ti = NULL; 34362306a36Sopenharmony_ci tio->clone = NULL; 34462306a36Sopenharmony_ci tio->orig = rq; 34562306a36Sopenharmony_ci tio->error = 0; 34662306a36Sopenharmony_ci tio->completed = 0; 34762306a36Sopenharmony_ci /* 34862306a36Sopenharmony_ci * Avoid initializing info for blk-mq; it passes 34962306a36Sopenharmony_ci * target-specific data through info.ptr 35062306a36Sopenharmony_ci * (see: dm_mq_init_request) 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci if (!md->init_tio_pdu) 35362306a36Sopenharmony_ci memset(&tio->info, 0, sizeof(tio->info)); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci/* 35762306a36Sopenharmony_ci * Returns: 35862306a36Sopenharmony_ci * DM_MAPIO_* : the request has been processed as indicated 35962306a36Sopenharmony_ci * DM_MAPIO_REQUEUE : the original request needs to be immediately requeued 36062306a36Sopenharmony_ci * < 0 : the request was completed due to failure 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_cistatic int map_request(struct dm_rq_target_io *tio) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci int r; 36562306a36Sopenharmony_ci struct dm_target *ti = tio->ti; 36662306a36Sopenharmony_ci struct mapped_device *md = tio->md; 36762306a36Sopenharmony_ci struct request *rq = tio->orig; 36862306a36Sopenharmony_ci struct request *clone = NULL; 36962306a36Sopenharmony_ci blk_status_t ret; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci r = ti->type->clone_and_map_rq(ti, rq, &tio->info, &clone); 37262306a36Sopenharmony_ci switch (r) { 37362306a36Sopenharmony_ci case DM_MAPIO_SUBMITTED: 37462306a36Sopenharmony_ci /* The target has taken the I/O to submit by itself later */ 37562306a36Sopenharmony_ci break; 37662306a36Sopenharmony_ci case DM_MAPIO_REMAPPED: 37762306a36Sopenharmony_ci if (setup_clone(clone, rq, tio, GFP_ATOMIC)) { 37862306a36Sopenharmony_ci /* -ENOMEM */ 37962306a36Sopenharmony_ci ti->type->release_clone_rq(clone, &tio->info); 38062306a36Sopenharmony_ci return DM_MAPIO_REQUEUE; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* The target has remapped the I/O so dispatch it */ 38462306a36Sopenharmony_ci trace_block_rq_remap(clone, disk_devt(dm_disk(md)), 38562306a36Sopenharmony_ci blk_rq_pos(rq)); 38662306a36Sopenharmony_ci ret = blk_insert_cloned_request(clone); 38762306a36Sopenharmony_ci switch (ret) { 38862306a36Sopenharmony_ci case BLK_STS_OK: 38962306a36Sopenharmony_ci break; 39062306a36Sopenharmony_ci case BLK_STS_RESOURCE: 39162306a36Sopenharmony_ci case BLK_STS_DEV_RESOURCE: 39262306a36Sopenharmony_ci blk_rq_unprep_clone(clone); 39362306a36Sopenharmony_ci blk_mq_cleanup_rq(clone); 39462306a36Sopenharmony_ci tio->ti->type->release_clone_rq(clone, &tio->info); 39562306a36Sopenharmony_ci tio->clone = NULL; 39662306a36Sopenharmony_ci return DM_MAPIO_REQUEUE; 39762306a36Sopenharmony_ci default: 39862306a36Sopenharmony_ci /* must complete clone in terms of original request */ 39962306a36Sopenharmony_ci dm_complete_request(rq, ret); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci case DM_MAPIO_REQUEUE: 40362306a36Sopenharmony_ci /* The target wants to requeue the I/O */ 40462306a36Sopenharmony_ci break; 40562306a36Sopenharmony_ci case DM_MAPIO_DELAY_REQUEUE: 40662306a36Sopenharmony_ci /* The target wants to requeue the I/O after a delay */ 40762306a36Sopenharmony_ci dm_requeue_original_request(tio, true); 40862306a36Sopenharmony_ci break; 40962306a36Sopenharmony_ci case DM_MAPIO_KILL: 41062306a36Sopenharmony_ci /* The target wants to complete the I/O */ 41162306a36Sopenharmony_ci dm_kill_unmapped_request(rq, BLK_STS_IOERR); 41262306a36Sopenharmony_ci break; 41362306a36Sopenharmony_ci default: 41462306a36Sopenharmony_ci DMCRIT("unimplemented target map return value: %d", r); 41562306a36Sopenharmony_ci BUG(); 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return r; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci/* DEPRECATED: previously used for request-based merge heuristic in dm_request_fn() */ 42262306a36Sopenharmony_cissize_t dm_attr_rq_based_seq_io_merge_deadline_show(struct mapped_device *md, char *buf) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci return sprintf(buf, "%u\n", 0); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cissize_t dm_attr_rq_based_seq_io_merge_deadline_store(struct mapped_device *md, 42862306a36Sopenharmony_ci const char *buf, size_t count) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci return count; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic void dm_start_request(struct mapped_device *md, struct request *orig) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci blk_mq_start_request(orig); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (unlikely(dm_stats_used(&md->stats))) { 43862306a36Sopenharmony_ci struct dm_rq_target_io *tio = tio_from_request(orig); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci tio->duration_jiffies = jiffies; 44162306a36Sopenharmony_ci tio->n_sectors = blk_rq_sectors(orig); 44262306a36Sopenharmony_ci dm_stats_account_io(&md->stats, rq_data_dir(orig), 44362306a36Sopenharmony_ci blk_rq_pos(orig), tio->n_sectors, false, 0, 44462306a36Sopenharmony_ci &tio->stats_aux); 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* 44862306a36Sopenharmony_ci * Hold the md reference here for the in-flight I/O. 44962306a36Sopenharmony_ci * We can't rely on the reference count by device opener, 45062306a36Sopenharmony_ci * because the device may be closed during the request completion 45162306a36Sopenharmony_ci * when all bios are completed. 45262306a36Sopenharmony_ci * See the comment in rq_completed() too. 45362306a36Sopenharmony_ci */ 45462306a36Sopenharmony_ci dm_get(md); 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic int dm_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, 45862306a36Sopenharmony_ci unsigned int hctx_idx, unsigned int numa_node) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci struct mapped_device *md = set->driver_data; 46162306a36Sopenharmony_ci struct dm_rq_target_io *tio = blk_mq_rq_to_pdu(rq); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* 46462306a36Sopenharmony_ci * Must initialize md member of tio, otherwise it won't 46562306a36Sopenharmony_ci * be available in dm_mq_queue_rq. 46662306a36Sopenharmony_ci */ 46762306a36Sopenharmony_ci tio->md = md; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci if (md->init_tio_pdu) { 47062306a36Sopenharmony_ci /* target-specific per-io data is immediately after the tio */ 47162306a36Sopenharmony_ci tio->info.ptr = tio + 1; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, 47862306a36Sopenharmony_ci const struct blk_mq_queue_data *bd) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct request *rq = bd->rq; 48162306a36Sopenharmony_ci struct dm_rq_target_io *tio = blk_mq_rq_to_pdu(rq); 48262306a36Sopenharmony_ci struct mapped_device *md = tio->md; 48362306a36Sopenharmony_ci struct dm_target *ti = md->immutable_target; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* 48662306a36Sopenharmony_ci * blk-mq's unquiesce may come from outside events, such as 48762306a36Sopenharmony_ci * elevator switch, updating nr_requests or others, and request may 48862306a36Sopenharmony_ci * come during suspend, so simply ask for blk-mq to requeue it. 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) 49162306a36Sopenharmony_ci return BLK_STS_RESOURCE; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (unlikely(!ti)) { 49462306a36Sopenharmony_ci int srcu_idx; 49562306a36Sopenharmony_ci struct dm_table *map; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci map = dm_get_live_table(md, &srcu_idx); 49862306a36Sopenharmony_ci if (unlikely(!map)) { 49962306a36Sopenharmony_ci dm_put_live_table(md, srcu_idx); 50062306a36Sopenharmony_ci return BLK_STS_RESOURCE; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci ti = dm_table_find_target(map, 0); 50362306a36Sopenharmony_ci dm_put_live_table(md, srcu_idx); 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (ti->type->busy && ti->type->busy(ti)) 50762306a36Sopenharmony_ci return BLK_STS_RESOURCE; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci dm_start_request(md, rq); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* Init tio using md established in .init_request */ 51262306a36Sopenharmony_ci init_tio(tio, rq, md); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* 51562306a36Sopenharmony_ci * Establish tio->ti before calling map_request(). 51662306a36Sopenharmony_ci */ 51762306a36Sopenharmony_ci tio->ti = ti; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* Direct call is fine since .queue_rq allows allocations */ 52062306a36Sopenharmony_ci if (map_request(tio) == DM_MAPIO_REQUEUE) { 52162306a36Sopenharmony_ci /* Undo dm_start_request() before requeuing */ 52262306a36Sopenharmony_ci rq_end_stats(md, rq); 52362306a36Sopenharmony_ci rq_completed(md); 52462306a36Sopenharmony_ci return BLK_STS_RESOURCE; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci return BLK_STS_OK; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic const struct blk_mq_ops dm_mq_ops = { 53162306a36Sopenharmony_ci .queue_rq = dm_mq_queue_rq, 53262306a36Sopenharmony_ci .complete = dm_softirq_done, 53362306a36Sopenharmony_ci .init_request = dm_mq_init_request, 53462306a36Sopenharmony_ci}; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ciint dm_mq_init_request_queue(struct mapped_device *md, struct dm_table *t) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci struct dm_target *immutable_tgt; 53962306a36Sopenharmony_ci int err; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci md->tag_set = kzalloc_node(sizeof(struct blk_mq_tag_set), GFP_KERNEL, md->numa_node_id); 54262306a36Sopenharmony_ci if (!md->tag_set) 54362306a36Sopenharmony_ci return -ENOMEM; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci md->tag_set->ops = &dm_mq_ops; 54662306a36Sopenharmony_ci md->tag_set->queue_depth = dm_get_blk_mq_queue_depth(); 54762306a36Sopenharmony_ci md->tag_set->numa_node = md->numa_node_id; 54862306a36Sopenharmony_ci md->tag_set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_STACKING; 54962306a36Sopenharmony_ci md->tag_set->nr_hw_queues = dm_get_blk_mq_nr_hw_queues(); 55062306a36Sopenharmony_ci md->tag_set->driver_data = md; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci md->tag_set->cmd_size = sizeof(struct dm_rq_target_io); 55362306a36Sopenharmony_ci immutable_tgt = dm_table_get_immutable_target(t); 55462306a36Sopenharmony_ci if (immutable_tgt && immutable_tgt->per_io_data_size) { 55562306a36Sopenharmony_ci /* any target-specific per-io data is immediately after the tio */ 55662306a36Sopenharmony_ci md->tag_set->cmd_size += immutable_tgt->per_io_data_size; 55762306a36Sopenharmony_ci md->init_tio_pdu = true; 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci err = blk_mq_alloc_tag_set(md->tag_set); 56162306a36Sopenharmony_ci if (err) 56262306a36Sopenharmony_ci goto out_kfree_tag_set; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci err = blk_mq_init_allocated_queue(md->tag_set, md->queue); 56562306a36Sopenharmony_ci if (err) 56662306a36Sopenharmony_ci goto out_tag_set; 56762306a36Sopenharmony_ci return 0; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ciout_tag_set: 57062306a36Sopenharmony_ci blk_mq_free_tag_set(md->tag_set); 57162306a36Sopenharmony_ciout_kfree_tag_set: 57262306a36Sopenharmony_ci kfree(md->tag_set); 57362306a36Sopenharmony_ci md->tag_set = NULL; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci return err; 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_civoid dm_mq_cleanup_mapped_device(struct mapped_device *md) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci if (md->tag_set) { 58162306a36Sopenharmony_ci blk_mq_free_tag_set(md->tag_set); 58262306a36Sopenharmony_ci kfree(md->tag_set); 58362306a36Sopenharmony_ci md->tag_set = NULL; 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cimodule_param(reserved_rq_based_ios, uint, 0644); 58862306a36Sopenharmony_ciMODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools"); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/* Unused, but preserved for userspace compatibility */ 59162306a36Sopenharmony_cistatic bool use_blk_mq = true; 59262306a36Sopenharmony_cimodule_param(use_blk_mq, bool, 0644); 59362306a36Sopenharmony_ciMODULE_PARM_DESC(use_blk_mq, "Use block multiqueue for request-based DM devices"); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cimodule_param(dm_mq_nr_hw_queues, uint, 0644); 59662306a36Sopenharmony_ciMODULE_PARM_DESC(dm_mq_nr_hw_queues, "Number of hardware queues for request-based dm-mq devices"); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cimodule_param(dm_mq_queue_depth, uint, 0644); 59962306a36Sopenharmony_ciMODULE_PARM_DESC(dm_mq_queue_depth, "Queue depth for request-based dm-mq devices"); 600