diff options
Diffstat (limited to 'drivers/md/dm-rq.c')
| -rw-r--r-- | drivers/md/dm-rq.c | 94 |
1 files changed, 50 insertions, 44 deletions
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 0dbd48cbdff9..a6ca92049c10 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2016 Red Hat, Inc. All rights reserved. * @@ -7,7 +8,6 @@ #include "dm-core.h" #include "dm-rq.h" -#include <linux/elevator.h> /* for rq_end_sector() */ #include <linux/blk-mq.h> #define DM_MSG_PREFIX "core-rq" @@ -24,34 +24,33 @@ struct dm_rq_target_io { union map_info info; struct dm_stats_aux stats_aux; unsigned long duration_jiffies; - unsigned n_sectors; - unsigned completed; + unsigned int n_sectors; + unsigned int completed; }; #define DM_MQ_NR_HW_QUEUES 1 #define DM_MQ_QUEUE_DEPTH 2048 -static unsigned dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES; -static unsigned dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH; +static unsigned int dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES; +static unsigned int dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH; /* * Request-based DM's mempools' reserved IOs set by the user. */ #define RESERVED_REQUEST_BASED_IOS 256 -static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS; +static unsigned int reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS; -unsigned dm_get_reserved_rq_based_ios(void) +unsigned int dm_get_reserved_rq_based_ios(void) { return __dm_get_module_param(&reserved_rq_based_ios, RESERVED_REQUEST_BASED_IOS, DM_RESERVED_MAX_IOS); } -EXPORT_SYMBOL_GPL(dm_get_reserved_rq_based_ios); -static unsigned dm_get_blk_mq_nr_hw_queues(void) +static unsigned int dm_get_blk_mq_nr_hw_queues(void) { return __dm_get_module_param(&dm_mq_nr_hw_queues, 1, 32); } -static unsigned dm_get_blk_mq_queue_depth(void) +static unsigned int dm_get_blk_mq_queue_depth(void) { return __dm_get_module_param(&dm_mq_queue_depth, DM_MQ_QUEUE_DEPTH, BLK_MQ_MAX_DEPTH); @@ -129,6 +128,7 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig) { if (unlikely(dm_stats_used(&md->stats))) { struct dm_rq_target_io *tio = tio_from_request(orig); + tio->duration_jiffies = jiffies - tio->duration_jiffies; dm_stats_account_io(&md->stats, rq_data_dir(orig), blk_rq_pos(orig), tio->n_sectors, true, @@ -217,13 +217,10 @@ static void dm_done(struct request *clone, blk_status_t error, bool mapped) if (unlikely(error == BLK_STS_TARGET)) { if (req_op(clone) == REQ_OP_DISCARD && !clone->q->limits.max_discard_sectors) - disable_discard(tio->md); - else if (req_op(clone) == REQ_OP_WRITE_SAME && - !clone->q->limits.max_write_same_sectors) - disable_write_same(tio->md); + blk_queue_disable_discard(tio->md->queue); else if (req_op(clone) == REQ_OP_WRITE_ZEROES && !clone->q->limits.max_write_zeroes_sectors) - disable_write_zeroes(tio->md); + blk_queue_disable_write_zeroes(tio->md->queue); } switch (r) { @@ -243,7 +240,7 @@ static void dm_done(struct request *clone, blk_status_t error, bool mapped) dm_requeue_original_request(tio, true); break; default: - DMWARN("unimplemented target endio return value: %d", r); + DMCRIT("unimplemented target endio return value: %d", r); BUG(); } } @@ -297,26 +294,13 @@ static void dm_kill_unmapped_request(struct request *rq, blk_status_t error) dm_complete_request(rq, error); } -static void end_clone_request(struct request *clone, blk_status_t error) +static enum rq_end_io_ret end_clone_request(struct request *clone, + blk_status_t error) { struct dm_rq_target_io *tio = clone->end_io_data; dm_complete_request(tio->orig, error); -} - -static blk_status_t dm_dispatch_clone_request(struct request *clone, struct request *rq) -{ - blk_status_t r; - - if (blk_queue_io_stat(clone->q)) - clone->rq_flags |= RQF_IO_STAT; - - clone->start_time_ns = ktime_get_ns(); - r = blk_insert_cloned_request(clone->q, clone); - if (r != BLK_STS_OK && r != BLK_STS_RESOURCE && r != BLK_STS_DEV_RESOURCE) - /* must complete clone in terms of original request */ - dm_complete_request(rq, r); - return r; + return RQ_END_IO_NONE; } static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig, @@ -338,7 +322,7 @@ static int setup_clone(struct request *clone, struct request *rq, { int r; - r = blk_rq_prep_clone(clone, rq, &tio->md->bs, gfp_mask, + r = blk_rq_prep_clone(clone, rq, &tio->md->mempools->bs, gfp_mask, dm_rq_bio_constructor, tio); if (r) return r; @@ -399,13 +383,20 @@ static int map_request(struct dm_rq_target_io *tio) /* The target has remapped the I/O so dispatch it */ trace_block_rq_remap(clone, disk_devt(dm_disk(md)), blk_rq_pos(rq)); - ret = dm_dispatch_clone_request(clone, rq); - if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) { + ret = blk_insert_cloned_request(clone); + switch (ret) { + case BLK_STS_OK: + break; + case BLK_STS_RESOURCE: + case BLK_STS_DEV_RESOURCE: blk_rq_unprep_clone(clone); blk_mq_cleanup_rq(clone); tio->ti->type->release_clone_rq(clone, &tio->info); tio->clone = NULL; return DM_MAPIO_REQUEUE; + default: + /* must complete clone in terms of original request */ + dm_complete_request(rq, ret); } break; case DM_MAPIO_REQUEUE: @@ -420,7 +411,7 @@ static int map_request(struct dm_rq_target_io *tio) dm_kill_unmapped_request(rq, BLK_STS_IOERR); break; default: - DMWARN("unimplemented target map return value: %d", r); + DMCRIT("unimplemented target map return value: %d", r); BUG(); } @@ -445,6 +436,7 @@ static void dm_start_request(struct mapped_device *md, struct request *orig) if (unlikely(dm_stats_used(&md->stats))) { struct dm_rq_target_io *tio = tio_from_request(orig); + tio->duration_jiffies = jiffies; tio->n_sectors = blk_rq_sectors(orig); dm_stats_account_io(&md->stats, rq_data_dir(orig), @@ -490,10 +482,25 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, struct mapped_device *md = tio->md; struct dm_target *ti = md->immutable_target; + /* + * blk-mq's unquiesce may come from outside events, such as + * elevator switch, updating nr_requests or others, and request may + * come during suspend, so simply ask for blk-mq to requeue it. + */ + if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) + return BLK_STS_RESOURCE; + if (unlikely(!ti)) { int srcu_idx; - struct dm_table *map = dm_get_live_table(md, &srcu_idx); - + struct dm_table *map; + + map = dm_get_live_table(md, &srcu_idx); + if (unlikely(!map)) { + DMERR_LIMIT("%s: mapping table unavailable, erroring io", + dm_device_name(md)); + dm_put_live_table(md, srcu_idx); + return BLK_STS_IOERR; + } ti = dm_table_find_target(map, 0); dm_put_live_table(md, srcu_idx); } @@ -540,7 +547,7 @@ int dm_mq_init_request_queue(struct mapped_device *md, struct dm_table *t) md->tag_set->ops = &dm_mq_ops; md->tag_set->queue_depth = dm_get_blk_mq_queue_depth(); md->tag_set->numa_node = md->numa_node_id; - md->tag_set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_STACKING; + md->tag_set->flags = BLK_MQ_F_STACKING; md->tag_set->nr_hw_queues = dm_get_blk_mq_nr_hw_queues(); md->tag_set->driver_data = md; @@ -559,7 +566,6 @@ int dm_mq_init_request_queue(struct mapped_device *md, struct dm_table *t) err = blk_mq_init_allocated_queue(md->tag_set, md->queue); if (err) goto out_tag_set; - elevator_init_mq(md->queue); return 0; out_tag_set: @@ -580,16 +586,16 @@ void dm_mq_cleanup_mapped_device(struct mapped_device *md) } } -module_param(reserved_rq_based_ios, uint, S_IRUGO | S_IWUSR); +module_param(reserved_rq_based_ios, uint, 0644); MODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools"); /* Unused, but preserved for userspace compatibility */ static bool use_blk_mq = true; -module_param(use_blk_mq, bool, S_IRUGO | S_IWUSR); +module_param(use_blk_mq, bool, 0644); MODULE_PARM_DESC(use_blk_mq, "Use block multiqueue for request-based DM devices"); -module_param(dm_mq_nr_hw_queues, uint, S_IRUGO | S_IWUSR); +module_param(dm_mq_nr_hw_queues, uint, 0644); MODULE_PARM_DESC(dm_mq_nr_hw_queues, "Number of hardware queues for request-based dm-mq devices"); -module_param(dm_mq_queue_depth, uint, S_IRUGO | S_IWUSR); +module_param(dm_mq_queue_depth, uint, 0644); MODULE_PARM_DESC(dm_mq_queue_depth, "Queue depth for request-based dm-mq devices"); |
