diff options
Diffstat (limited to '0140-dm-fix-bio_set-allocation.patch')
-rw-r--r-- | 0140-dm-fix-bio_set-allocation.patch | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/0140-dm-fix-bio_set-allocation.patch b/0140-dm-fix-bio_set-allocation.patch new file mode 100644 index 000000000000..a3c7dbfedd06 --- /dev/null +++ b/0140-dm-fix-bio_set-allocation.patch @@ -0,0 +1,232 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig <hch@lst.de> +Date: Wed, 8 Jun 2022 08:34:06 +0200 +Subject: [PATCH] dm: fix bio_set allocation + +commit 29dec90a0f1d961b93f34f910e9319d8cb23edbd upstream. + +The use of bioset_init_from_src mean that the pre-allocated pools weren't +used for anything except parameter passing, and the integrity pool +creation got completely lost for the actual live mapped_device. Fix that +by assigning the actual preallocated dm_md_mempools to the mapped_device +and using that for I/O instead of creating new mempools. + +Fixes: 2a2a4c510b76 ("dm: use bioset_init_from_src() to copy bio_set") +Signed-off-by: Christoph Hellwig <hch@lst.de> +Signed-off-by: Mike Snitzer <snitzer@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/md/dm-core.h | 11 ++++-- + drivers/md/dm-rq.c | 2 +- + drivers/md/dm-table.c | 11 ------ + drivers/md/dm.c | 83 +++++++++++++------------------------------ + drivers/md/dm.h | 2 -- + 5 files changed, 34 insertions(+), 75 deletions(-) + +diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h +index 4277853c753515135c90391be507599cd827f573..3cd78f1e82a44fa9416927c5828254e10431b93a 100644 +--- a/drivers/md/dm-core.h ++++ b/drivers/md/dm-core.h +@@ -32,6 +32,14 @@ struct dm_kobject_holder { + * access their members! + */ + ++/* ++ * For mempools pre-allocation at the table loading time. ++ */ ++struct dm_md_mempools { ++ struct bio_set bs; ++ struct bio_set io_bs; ++}; ++ + struct mapped_device { + struct mutex suspend_lock; + +@@ -109,8 +117,7 @@ struct mapped_device { + /* + * io objects are allocated from here. + */ +- struct bio_set io_bs; +- struct bio_set bs; ++ struct dm_md_mempools *mempools; + + /* kobject and completion */ + struct dm_kobject_holder kobj_holder; +diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c +index 6087cdcaad46df50cb786fdb1f23b41efdf030a6..a83b98a8d2a993e75debd263ebefa369075c4080 100644 +--- a/drivers/md/dm-rq.c ++++ b/drivers/md/dm-rq.c +@@ -319,7 +319,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; +diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c +index 03541cfc2317cb0e17780fa8970ab8959d47b171..4b5cf337269950b5332cc1bd7c02f393d098e880 100644 +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -1030,17 +1030,6 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device * + return 0; + } + +-void dm_table_free_md_mempools(struct dm_table *t) +-{ +- dm_free_md_mempools(t->mempools); +- t->mempools = NULL; +-} +- +-struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t) +-{ +- return t->mempools; +-} +- + static int setup_indexes(struct dm_table *t) + { + int i; +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index a68316f96350d0af64c1db865c48d1e97fbf95ca..83dd17abf1af95844d85fd405acc0e360890ef43 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -131,14 +131,6 @@ static int get_swap_bios(void) + return latch; + } + +-/* +- * For mempools pre-allocation at the table loading time. +- */ +-struct dm_md_mempools { +- struct bio_set bs; +- struct bio_set io_bs; +-}; +- + struct table_device { + struct list_head list; + refcount_t count; +@@ -573,7 +565,7 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) + struct dm_target_io *tio; + struct bio *clone; + +- clone = bio_alloc_clone(bio->bi_bdev, bio, GFP_NOIO, &md->io_bs); ++ clone = bio_alloc_clone(bio->bi_bdev, bio, GFP_NOIO, &md->mempools->io_bs); + + tio = clone_to_tio(clone); + tio->flags = 0; +@@ -615,7 +607,7 @@ static struct bio *alloc_tio(struct clone_info *ci, struct dm_target *ti, + clone = &tio->clone; + } else { + clone = bio_alloc_clone(ci->bio->bi_bdev, ci->bio, +- gfp_mask, &ci->io->md->bs); ++ gfp_mask, &ci->io->md->mempools->bs); + if (!clone) + return NULL; + +@@ -1775,8 +1767,7 @@ static void cleanup_mapped_device(struct mapped_device *md) + { + if (md->wq) + destroy_workqueue(md->wq); +- bioset_exit(&md->bs); +- bioset_exit(&md->io_bs); ++ dm_free_md_mempools(md->mempools); + + if (md->dax_dev) { + dax_remove_host(md->disk); +@@ -1948,48 +1939,6 @@ static void free_dev(struct mapped_device *md) + kvfree(md); + } + +-static int __bind_mempools(struct mapped_device *md, struct dm_table *t) +-{ +- struct dm_md_mempools *p = dm_table_get_md_mempools(t); +- int ret = 0; +- +- if (dm_table_bio_based(t)) { +- /* +- * The md may already have mempools that need changing. +- * If so, reload bioset because front_pad may have changed +- * because a different table was loaded. +- */ +- bioset_exit(&md->bs); +- bioset_exit(&md->io_bs); +- +- } else if (bioset_initialized(&md->bs)) { +- /* +- * There's no need to reload with request-based dm +- * because the size of front_pad doesn't change. +- * Note for future: If you are to reload bioset, +- * prep-ed requests in the queue may refer +- * to bio from the old bioset, so you must walk +- * through the queue to unprep. +- */ +- goto out; +- } +- +- BUG_ON(!p || +- bioset_initialized(&md->bs) || +- bioset_initialized(&md->io_bs)); +- +- ret = bioset_init_from_src(&md->bs, &p->bs); +- if (ret) +- goto out; +- ret = bioset_init_from_src(&md->io_bs, &p->io_bs); +- if (ret) +- bioset_exit(&md->bs); +-out: +- /* mempool bind completed, no longer need any mempools in the table */ +- dm_table_free_md_mempools(t); +- return ret; +-} +- + /* + * Bind a table to the device. + */ +@@ -2043,12 +1992,28 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, + * immutable singletons - used to optimize dm_mq_queue_rq. + */ + md->immutable_target = dm_table_get_immutable_target(t); +- } + +- ret = __bind_mempools(md, t); +- if (ret) { +- old_map = ERR_PTR(ret); +- goto out; ++ /* ++ * There is no need to reload with request-based dm because the ++ * size of front_pad doesn't change. ++ * ++ * Note for future: If you are to reload bioset, prep-ed ++ * requests in the queue may refer to bio from the old bioset, ++ * so you must walk through the queue to unprep. ++ */ ++ if (!md->mempools) { ++ md->mempools = t->mempools; ++ t->mempools = NULL; ++ } ++ } else { ++ /* ++ * The md may already have mempools that need changing. ++ * If so, reload bioset because front_pad may have changed ++ * because a different table was loaded. ++ */ ++ dm_free_md_mempools(md->mempools); ++ md->mempools = t->mempools; ++ t->mempools = NULL; + } + + ret = dm_table_set_restrictions(t, md->queue, limits); +diff --git a/drivers/md/dm.h b/drivers/md/dm.h +index 9013dc1a7b0028cc98c2e99742ec5be487a753ba..968199b95fd1e216e33fbc2de208da0c9667544a 100644 +--- a/drivers/md/dm.h ++++ b/drivers/md/dm.h +@@ -71,8 +71,6 @@ struct dm_target *dm_table_get_immutable_target(struct dm_table *t); + struct dm_target *dm_table_get_wildcard_target(struct dm_table *t); + bool dm_table_bio_based(struct dm_table *t); + bool dm_table_request_based(struct dm_table *t); +-void dm_table_free_md_mempools(struct dm_table *t); +-struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); + + void dm_lock_md_type(struct mapped_device *md); + void dm_unlock_md_type(struct mapped_device *md); |