aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2012-06-02 19:30:00 -0400
committerAlasdair G Kergon <agk@redhat.com>2012-06-02 19:30:00 -0400
commita24c25696b7133dd534d7a9436e576af79d9ce3b (patch)
tree7b8b429aec7d7b2cebfbfbba0047911dc79290aa
parent35991652baa12ff3d0e420c0d0cb2ad9f7076e5b (diff)
dm thin: use slab mempools
Use dedicated caches prefixed with a "dm_" name rather than relying on kmalloc mempools backed by generic slab caches so the memory usage of thin provisioning (and any leaks) can be accounted for independently. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-thin.c161
1 files changed, 99 insertions, 62 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index eb3d138ff55a..db1b041ce975 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -111,7 +111,7 @@ struct cell_key {
111 dm_block_t block; 111 dm_block_t block;
112}; 112};
113 113
114struct cell { 114struct dm_bio_prison_cell {
115 struct hlist_node list; 115 struct hlist_node list;
116 struct bio_prison *prison; 116 struct bio_prison *prison;
117 struct cell_key key; 117 struct cell_key key;
@@ -141,6 +141,8 @@ static uint32_t calc_nr_buckets(unsigned nr_cells)
141 return n; 141 return n;
142} 142}
143 143
144static struct kmem_cache *_cell_cache;
145
144/* 146/*
145 * @nr_cells should be the number of cells you want in use _concurrently_. 147 * @nr_cells should be the number of cells you want in use _concurrently_.
146 * Don't confuse it with the number of distinct keys. 148 * Don't confuse it with the number of distinct keys.
@@ -157,8 +159,7 @@ static struct bio_prison *prison_create(unsigned nr_cells)
157 return NULL; 159 return NULL;
158 160
159 spin_lock_init(&prison->lock); 161 spin_lock_init(&prison->lock);
160 prison->cell_pool = mempool_create_kmalloc_pool(nr_cells, 162 prison->cell_pool = mempool_create_slab_pool(nr_cells, _cell_cache);
161 sizeof(struct cell));
162 if (!prison->cell_pool) { 163 if (!prison->cell_pool) {
163 kfree(prison); 164 kfree(prison);
164 return NULL; 165 return NULL;
@@ -194,10 +195,10 @@ static int keys_equal(struct cell_key *lhs, struct cell_key *rhs)
194 (lhs->block == rhs->block); 195 (lhs->block == rhs->block);
195} 196}
196 197
197static struct cell *__search_bucket(struct hlist_head *bucket, 198static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket,
198 struct cell_key *key) 199 struct cell_key *key)
199{ 200{
200 struct cell *cell; 201 struct dm_bio_prison_cell *cell;
201 struct hlist_node *tmp; 202 struct hlist_node *tmp;
202 203
203 hlist_for_each_entry(cell, tmp, bucket, list) 204 hlist_for_each_entry(cell, tmp, bucket, list)
@@ -214,12 +215,12 @@ static struct cell *__search_bucket(struct hlist_head *bucket,
214 * Returns 1 if the cell was already held, 0 if @inmate is the new holder. 215 * Returns 1 if the cell was already held, 0 if @inmate is the new holder.
215 */ 216 */
216static int bio_detain(struct bio_prison *prison, struct cell_key *key, 217static int bio_detain(struct bio_prison *prison, struct cell_key *key,
217 struct bio *inmate, struct cell **ref) 218 struct bio *inmate, struct dm_bio_prison_cell **ref)
218{ 219{
219 int r = 1; 220 int r = 1;
220 unsigned long flags; 221 unsigned long flags;
221 uint32_t hash = hash_key(prison, key); 222 uint32_t hash = hash_key(prison, key);
222 struct cell *cell, *cell2; 223 struct dm_bio_prison_cell *cell, *cell2;
223 224
224 BUG_ON(hash > prison->nr_buckets); 225 BUG_ON(hash > prison->nr_buckets);
225 226
@@ -273,7 +274,7 @@ out:
273/* 274/*
274 * @inmates must have been initialised prior to this call 275 * @inmates must have been initialised prior to this call
275 */ 276 */
276static void __cell_release(struct cell *cell, struct bio_list *inmates) 277static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
277{ 278{
278 struct bio_prison *prison = cell->prison; 279 struct bio_prison *prison = cell->prison;
279 280
@@ -287,7 +288,7 @@ static void __cell_release(struct cell *cell, struct bio_list *inmates)
287 mempool_free(cell, prison->cell_pool); 288 mempool_free(cell, prison->cell_pool);
288} 289}
289 290
290static void cell_release(struct cell *cell, struct bio_list *bios) 291static void cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios)
291{ 292{
292 unsigned long flags; 293 unsigned long flags;
293 struct bio_prison *prison = cell->prison; 294 struct bio_prison *prison = cell->prison;
@@ -303,7 +304,7 @@ static void cell_release(struct cell *cell, struct bio_list *bios)
303 * bio may be in the cell. This function releases the cell, and also does 304 * bio may be in the cell. This function releases the cell, and also does
304 * a sanity check. 305 * a sanity check.
305 */ 306 */
306static void __cell_release_singleton(struct cell *cell, struct bio *bio) 307static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
307{ 308{
308 BUG_ON(cell->holder != bio); 309 BUG_ON(cell->holder != bio);
309 BUG_ON(!bio_list_empty(&cell->bios)); 310 BUG_ON(!bio_list_empty(&cell->bios));
@@ -311,7 +312,7 @@ static void __cell_release_singleton(struct cell *cell, struct bio *bio)
311 __cell_release(cell, NULL); 312 __cell_release(cell, NULL);
312} 313}
313 314
314static void cell_release_singleton(struct cell *cell, struct bio *bio) 315static void cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
315{ 316{
316 unsigned long flags; 317 unsigned long flags;
317 struct bio_prison *prison = cell->prison; 318 struct bio_prison *prison = cell->prison;
@@ -324,7 +325,8 @@ static void cell_release_singleton(struct cell *cell, struct bio *bio)
324/* 325/*
325 * Sometimes we don't want the holder, just the additional bios. 326 * Sometimes we don't want the holder, just the additional bios.
326 */ 327 */
327static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates) 328static void __cell_release_no_holder(struct dm_bio_prison_cell *cell,
329 struct bio_list *inmates)
328{ 330{
329 struct bio_prison *prison = cell->prison; 331 struct bio_prison *prison = cell->prison;
330 332
@@ -334,7 +336,8 @@ static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates
334 mempool_free(cell, prison->cell_pool); 336 mempool_free(cell, prison->cell_pool);
335} 337}
336 338
337static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates) 339static void cell_release_no_holder(struct dm_bio_prison_cell *cell,
340 struct bio_list *inmates)
338{ 341{
339 unsigned long flags; 342 unsigned long flags;
340 struct bio_prison *prison = cell->prison; 343 struct bio_prison *prison = cell->prison;
@@ -344,7 +347,7 @@ static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
344 spin_unlock_irqrestore(&prison->lock, flags); 347 spin_unlock_irqrestore(&prison->lock, flags);
345} 348}
346 349
347static void cell_error(struct cell *cell) 350static void cell_error(struct dm_bio_prison_cell *cell)
348{ 351{
349 struct bio_prison *prison = cell->prison; 352 struct bio_prison *prison = cell->prison;
350 struct bio_list bios; 353 struct bio_list bios;
@@ -491,7 +494,7 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
491 * also provides the interface for creating and destroying internal 494 * also provides the interface for creating and destroying internal
492 * devices. 495 * devices.
493 */ 496 */
494struct new_mapping; 497struct dm_thin_new_mapping;
495 498
496struct pool_features { 499struct pool_features {
497 unsigned zero_new_blocks:1; 500 unsigned zero_new_blocks:1;
@@ -537,7 +540,7 @@ struct pool {
537 struct deferred_set shared_read_ds; 540 struct deferred_set shared_read_ds;
538 struct deferred_set all_io_ds; 541 struct deferred_set all_io_ds;
539 542
540 struct new_mapping *next_mapping; 543 struct dm_thin_new_mapping *next_mapping;
541 mempool_t *mapping_pool; 544 mempool_t *mapping_pool;
542 mempool_t *endio_hook_pool; 545 mempool_t *endio_hook_pool;
543}; 546};
@@ -630,11 +633,11 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev
630 633
631/*----------------------------------------------------------------*/ 634/*----------------------------------------------------------------*/
632 635
633struct endio_hook { 636struct dm_thin_endio_hook {
634 struct thin_c *tc; 637 struct thin_c *tc;
635 struct deferred_entry *shared_read_entry; 638 struct deferred_entry *shared_read_entry;
636 struct deferred_entry *all_io_entry; 639 struct deferred_entry *all_io_entry;
637 struct new_mapping *overwrite_mapping; 640 struct dm_thin_new_mapping *overwrite_mapping;
638}; 641};
639 642
640static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) 643static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
@@ -647,7 +650,8 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
647 bio_list_init(master); 650 bio_list_init(master);
648 651
649 while ((bio = bio_list_pop(&bios))) { 652 while ((bio = bio_list_pop(&bios))) {
650 struct endio_hook *h = dm_get_mapinfo(bio)->ptr; 653 struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
654
651