diff options
author | Kent Overstreet <koverstreet@google.com> | 2012-09-07 16:44:01 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-09-09 04:35:38 -0400 |
commit | 94818742316e27d01506240cf8b07d69844d31af (patch) | |
tree | d940b88519a4755422cfcfcffc63174b918fdc92 /drivers | |
parent | 1e2a410ff71504a64d1af2e354287ac51aeac1b0 (diff) |
dm: Use bioset's front_pad for dm_rq_clone_bio_info
Previously, dm_rq_clone_bio_info needed to be freed by the bio's
destructor to avoid a memory leak in the blk_rq_prep_clone() error path.
This gets rid of a memory allocation and means we can kill
dm_rq_bio_destructor.
The _rq_bio_info_cache kmem cache is unused now and needs to be deleted,
but due to the way io_pool is used and overloaded this looks not quite
trivial so I'm leaving it for a later patch.
v6: Fix comment on struct dm_rq_clone_bio_info, per Tejun
Signed-off-by: Kent Overstreet <koverstreet@google.com>
CC: Alasdair Kergon <agk@redhat.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm.c | 46 |
1 files changed, 18 insertions, 28 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f43aaf689bd0..33470f01ea5e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -86,12 +86,17 @@ struct dm_rq_target_io { | |||
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * For request-based dm. | 89 | * For request-based dm - the bio clones we allocate are embedded in these |
90 | * One of these is allocated per bio. | 90 | * structs. |
91 | * | ||
92 | * We allocate these with bio_alloc_bioset, using the front_pad parameter when | ||
93 | * the bioset is created - this means the bio has to come at the end of the | ||
94 | * struct. | ||
91 | */ | 95 | */ |
92 | struct dm_rq_clone_bio_info { | 96 | struct dm_rq_clone_bio_info { |
93 | struct bio *orig; | 97 | struct bio *orig; |
94 | struct dm_rq_target_io *tio; | 98 | struct dm_rq_target_io *tio; |
99 | struct bio clone; | ||
95 | }; | 100 | }; |
96 | 101 | ||
97 | union map_info *dm_get_mapinfo(struct bio *bio) | 102 | union map_info *dm_get_mapinfo(struct bio *bio) |
@@ -211,6 +216,11 @@ struct dm_md_mempools { | |||
211 | static struct kmem_cache *_io_cache; | 216 | static struct kmem_cache *_io_cache; |
212 | static struct kmem_cache *_tio_cache; | 217 | static struct kmem_cache *_tio_cache; |
213 | static struct kmem_cache *_rq_tio_cache; | 218 | static struct kmem_cache *_rq_tio_cache; |
219 | |||
220 | /* | ||
221 | * Unused now, and needs to be deleted. But since io_pool is overloaded and it's | ||
222 | * still used for _io_cache, I'm leaving this for a later cleanup | ||
223 | */ | ||
214 | static struct kmem_cache *_rq_bio_info_cache; | 224 | static struct kmem_cache *_rq_bio_info_cache; |
215 | 225 | ||
216 | static int __init local_init(void) | 226 | static int __init local_init(void) |
@@ -467,16 +477,6 @@ static void free_rq_tio(struct dm_rq_target_io *tio) | |||
467 | mempool_free(tio, tio->md->tio_pool); | 477 | mempool_free(tio, tio->md->tio_pool); |
468 | } | 478 | } |
469 | 479 | ||
470 | static struct dm_rq_clone_bio_info *alloc_bio_info(struct mapped_device *md) | ||
471 | { | ||
472 | return mempool_alloc(md->io_pool, GFP_ATOMIC); | ||
473 | } | ||
474 | |||
475 | static void free_bio_info(struct dm_rq_clone_bio_info *info) | ||
476 | { | ||
477 | mempool_free(info, info->tio->md->io_pool); | ||
478 | } | ||
479 | |||
480 | static int md_in_flight(struct mapped_device *md) | 480 | static int md_in_flight(struct mapped_device *md) |
481 | { | 481 | { |
482 | return atomic_read(&md->pending[READ]) + | 482 | return atomic_read(&md->pending[READ]) + |
@@ -1460,30 +1460,17 @@ void dm_dispatch_request(struct request *rq) | |||
1460 | } | 1460 | } |
1461 | EXPORT_SYMBOL_GPL(dm_dispatch_request); | 1461 | EXPORT_SYMBOL_GPL(dm_dispatch_request); |
1462 | 1462 | ||
1463 | static void dm_rq_bio_destructor(struct bio *bio) | ||
1464 | { | ||
1465 | struct dm_rq_clone_bio_info *info = bio->bi_private; | ||
1466 | struct mapped_device *md = info->tio->md; | ||
1467 | |||
1468 | free_bio_info(info); | ||
1469 | bio_free(bio, md->bs); | ||
1470 | } | ||
1471 | |||
1472 | static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig, | 1463 | static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig, |
1473 | void *data) | 1464 | void *data) |
1474 | { | 1465 | { |
1475 | struct dm_rq_target_io *tio = data; | 1466 | struct dm_rq_target_io *tio = data; |
1476 | struct mapped_device *md = tio->md; | 1467 | struct dm_rq_clone_bio_info *info = |
1477 | struct dm_rq_clone_bio_info *info = alloc_bio_info(md); | 1468 | container_of(bio, struct dm_rq_clone_bio_info, clone); |
1478 | |||
1479 | if (!info) | ||
1480 | return -ENOMEM; | ||
1481 | 1469 | ||
1482 | info->orig = bio_orig; | 1470 | info->orig = bio_orig; |
1483 | info->tio = tio; | 1471 | info->tio = tio; |
1484 | bio->bi_end_io = end_clone_bio; | 1472 | bio->bi_end_io = end_clone_bio; |
1485 | bio->bi_private = info; | 1473 | bio->bi_private = info; |
1486 | bio->bi_destructor = dm_rq_bio_destructor; | ||
1487 | 1474 | ||
1488 | return 0; | 1475 | return 0; |
1489 | } | 1476 | } |
@@ -2718,7 +2705,10 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | |||
2718 | if (!pools->tio_pool) | 2705 | if (!pools->tio_pool) |
2719 | goto free_io_pool_and_out; | 2706 | goto free_io_pool_and_out; |
2720 | 2707 | ||
2721 | pools->bs = bioset_create(pool_size, 0); | 2708 | pools->bs = (type == DM_TYPE_BIO_BASED) ? |
2709 | bioset_create(pool_size, 0) : | ||
2710 | bioset_create(pool_size, | ||
2711 | offsetof(struct dm_rq_clone_bio_info, clone)); | ||
2722 | if (!pools->bs) | 2712 | if (!pools->bs) |
2723 | goto free_tio_pool_and_out; | 2713 | goto free_tio_pool_and_out; |
2724 | 2714 | ||