dm: limit the number of bios in progress Limit the number of bios in progress to the nr_requests value. The default value is 1024. Signed-off-by: Mikulas Patocka --- drivers/md/dm.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) Index: linux-4.7-rc1/drivers/md/dm.c =================================================================== --- linux-4.7-rc1.orig/drivers/md/dm.c 2016-05-30 18:01:35.000000000 +0200 +++ linux-4.7-rc1/drivers/md/dm.c 2016-05-30 18:01:41.000000000 +0200 @@ -262,6 +262,8 @@ struct table_device { #define RESERVED_BIO_BASED_IOS 16 #define RESERVED_REQUEST_BASED_IOS 256 #define RESERVED_MAX_IOS 1024 +#define DEFAULT_NR_REQUESTS 1024 + static struct kmem_cache *_io_cache; static struct kmem_cache *_rq_tio_cache; static struct kmem_cache *_rq_cache; @@ -720,6 +722,12 @@ static void update_in_flight(struct mapp atomic_read(&md->pending[rw][1])); } +static bool limit_reached(struct mapped_device *md, int sync) +{ + return atomic_read(&md->pending[0][sync]) + + atomic_read(&md->pending[1][sync]) >= md->queue->nr_requests; +} + static void start_io_acct(struct dm_io *io) { struct mapped_device *md = io->md; @@ -735,6 +743,10 @@ static void start_io_acct(struct dm_io * rw = bio_data_dir(bio); sync = rw_is_sync(bio->bi_rw); + if (unlikely(limit_reached(md, sync))) + ___wait_event(md->wait, !limit_reached(md, sync), + TASK_UNINTERRUPTIBLE, 1, 0, io_schedule()); + atomic_inc(&md->pending[rw][sync]); update_in_flight(md, rw); @@ -767,12 +779,11 @@ static void end_io_acct(struct dm_io *io update_in_flight(md, rw); - pending += atomic_read(&md->pending[rw][sync^1]); pending += atomic_read(&md->pending[rw^1][sync]); - pending += atomic_read(&md->pending[rw^1][sync^1]); /* nudge anyone waiting on suspend queue */ - if (!pending) + if (unlikely(waitqueue_active(&md->wait)) && + pending < md->queue->nr_requests) wake_up(&md->wait); } @@ -2354,6 +2365,8 @@ static void dm_init_normal_md_queue(stru */ md->queue->backing_dev_info.congested_fn = dm_any_congested; blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); + + md->queue->nr_requests = DEFAULT_NR_REQUESTS; } static void cleanup_mapped_device(struct mapped_device *md)