diff options
| author | Mikulas Patocka <mpatocka@redhat.com> | 2008-07-21 07:00:35 -0400 |
|---|---|---|
| committer | Alasdair G Kergon <agk@redhat.com> | 2008-07-21 07:00:35 -0400 |
| commit | 92e868122edf08b9fc06b112e7e0c80ab94c1f93 (patch) | |
| tree | 9cd2e5e2f15adcaf1b8d3f8f55d5a676ad40bfd6 | |
| parent | a8d41b59f3f5a7ac19452ef442a7fc1b5fa17366 (diff) | |
dm snapshot: use per device mempools
Change snapshot per-module mempool to per-device mempool.
Per-module mempools could cause a deadlock if multiple
snapshot devices are stacked above each other.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
| -rw-r--r-- | drivers/md/dm-snap.c | 40 | ||||
| -rw-r--r-- | drivers/md/dm-snap.h | 2 |
2 files changed, 24 insertions, 18 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index f4fd0cee9c3d..6e5528aecc98 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -96,7 +96,6 @@ struct dm_snap_pending_exception { | |||
| 96 | */ | 96 | */ |
| 97 | static struct kmem_cache *exception_cache; | 97 | static struct kmem_cache *exception_cache; |
| 98 | static struct kmem_cache *pending_cache; | 98 | static struct kmem_cache *pending_cache; |
| 99 | static mempool_t *pending_pool; | ||
| 100 | 99 | ||
| 101 | struct dm_snap_tracked_chunk { | 100 | struct dm_snap_tracked_chunk { |
| 102 | struct hlist_node node; | 101 | struct hlist_node node; |
| @@ -364,14 +363,19 @@ static void free_exception(struct dm_snap_exception *e) | |||
| 364 | kmem_cache_free(exception_cache, e); | 363 | kmem_cache_free(exception_cache, e); |
| 365 | } | 364 | } |
| 366 | 365 | ||
| 367 | static struct dm_snap_pending_exception *alloc_pending_exception(void) | 366 | static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s) |
| 368 | { | 367 | { |
| 369 | return mempool_alloc(pending_pool, GFP_NOIO); | 368 | struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, |
| 369 | GFP_NOIO); | ||
| 370 | |||
| 371 | pe->snap = s; | ||
| 372 | |||
| 373 | return pe; | ||
| 370 | } | 374 | } |
| 371 | 375 | ||
| 372 | static void free_pending_exception(struct dm_snap_pending_exception *pe) | 376 | static void free_pending_exception(struct dm_snap_pending_exception *pe) |
| 373 | { | 377 | { |
| 374 | mempool_free(pe, pending_pool); | 378 | mempool_free(pe, pe->snap->pending_pool); |
| 375 | } | 379 | } |
| 376 | 380 | ||
| 377 | static void insert_completed_exception(struct dm_snapshot *s, | 381 | static void insert_completed_exception(struct dm_snapshot *s, |
| @@ -627,12 +631,18 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 627 | goto bad5; | 631 | goto bad5; |
| 628 | } | 632 | } |
| 629 | 633 | ||
| 634 | s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache); | ||
| 635 | if (!s->pending_pool) { | ||
| 636 | ti->error = "Could not allocate mempool for pending exceptions"; | ||
| 637 | goto bad6; | ||
| 638 | } | ||
| 639 | |||
| 630 | s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS, | 640 | s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS, |
| 631 | tracked_chunk_cache); | 641 | tracked_chunk_cache); |
| 632 | if (!s->tracked_chunk_pool) { | 642 | if (!s->tracked_chunk_pool) { |
| 633 | ti->error = "Could not allocate tracked_chunk mempool for " | 643 | ti->error = "Could not allocate tracked_chunk mempool for " |
| 634 | "tracking reads"; | 644 | "tracking reads"; |
| 635 | goto bad6; | 645 | goto bad_tracked_chunk_pool; |
| 636 | } | 646 | } |
| 637 | 647 | ||
| 638 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) | 648 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) |
| @@ -669,6 +679,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 669 | bad_load_and_register: | 679 | bad_load_and_register: |
| 670 | mempool_destroy(s->tracked_chunk_pool); | 680 | mempool_destroy(s->tracked_chunk_pool); |
| 671 | 681 | ||
| 682 | bad_tracked_chunk_pool: | ||
| 683 | mempool_destroy(s->pending_pool); | ||
| 684 | |||
| 672 | bad6: | 685 | bad6: |
| 673 | dm_kcopyd_client_destroy(s->kcopyd_client); | 686 | dm_kcopyd_client_destroy(s->kcopyd_client); |
| 674 | 687 | ||
| @@ -723,6 +736,8 @@ static void snapshot_dtr(struct dm_target *ti) | |||
| 723 | 736 | ||
| 724 | __free_exceptions(s); | 737 | __free_exceptions(s); |
| 725 | 738 | ||
| 739 | mempool_destroy(s->pending_pool); | ||
| 740 | |||
| 726 | dm_put_device(ti, s->origin); | 741 | dm_put_device(ti, s->origin); |
| 727 | dm_put_device(ti, s->cow); | 742 | dm_put_device(ti, s->cow); |
| 728 | 743 | ||
| @@ -969,7 +984,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) | |||
| 969 | * to hold the lock while we do this. | 984 | * to hold the lock while we do this. |
| 970 | */ | 985 | */ |
| 971 | up_write(&s->lock); | 986 | up_write(&s->lock); |
| 972 | pe = alloc_pending_exception(); | 987 | pe = alloc_pending_exception(s); |
| 973 | down_write(&s->lock); | 988 | down_write(&s->lock); |
| 974 | 989 | ||
| 975 | if (!s->valid) { | 990 | if (!s->valid) { |
| @@ -989,7 +1004,6 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) | |||
| 989 | bio_list_init(&pe->snapshot_bios); | 1004 | bio_list_init(&pe->snapshot_bios); |
| 990 | pe->primary_pe = NULL; | 1005 | pe->primary_pe = NULL; |
| 991 | atomic_set(&pe->ref_count, 0); | 1006 | atomic_set(&pe->ref_count, 0); |
| 992 | pe->snap = s; | ||
| 993 | pe->started = 0; | 1007 | pe->started = 0; |
| 994 | 1008 | ||
| 995 | if (s->store.prepare_exception(&s->store, &pe->e)) { | 1009 | if (s->store.prepare_exception(&s->store, &pe->e)) { |
| @@ -1418,24 +1432,15 @@ static int __init dm_snapshot_init(void) | |||
| 1418 | goto bad5; | 1432 | goto bad5; |
| 1419 | } | 1433 | } |
| 1420 | 1434 | ||
| 1421 | pending_pool = mempool_create_slab_pool(128, pending_cache); | ||
| 1422 | if (!pending_pool) { | ||
| 1423 | DMERR("Couldn't create pending pool."); | ||
| 1424 | r = -ENOMEM; | ||
| 1425 | goto bad_pending_pool; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | ksnapd = create_singlethread_workqueue("ksnapd"); | 1435 | ksnapd = create_singlethread_workqueue("ksnapd"); |
| 1429 | if (!ksnapd) { | 1436 | if (!ksnapd) { |
| 1430 | DMERR("Failed to create ksnapd workqueue."); | 1437 | DMERR("Failed to create ksnapd workqueue."); |
| 1431 | r = -ENOMEM; | 1438 | r = -ENOMEM; |
| 1432 | goto bad6; | 1439 | goto bad_pending_pool; |
| 1433 | } | 1440 | } |
| 1434 | 1441 | ||
| 1435 | return 0; | 1442 | return 0; |
| 1436 | 1443 | ||
| 1437 | bad6: | ||
| 1438 | mempool_destroy(pending_pool); | ||
| 1439 | bad_pending_pool: | 1444 | bad_pending_pool: |
| 1440 | kmem_cache_destroy(tracked_chunk_cache); | 1445 | kmem_cache_destroy(tracked_chunk_cache); |
| 1441 | bad5: | 1446 | bad5: |
| @@ -1466,7 +1471,6 @@ static void __exit dm_snapshot_exit(void) | |||
| 1466 | DMERR("origin unregister failed %d", r); | 1471 | DMERR("origin unregister failed %d", r); |
| 1467 | 1472 | ||
| 1468 | exit_origin_hash(); | 1473 | exit_origin_hash(); |
| 1469 | mempool_destroy(pending_pool); | ||
| 1470 | kmem_cache_destroy(pending_cache); | 1474 | kmem_cache_destroy(pending_cache); |
| 1471 | kmem_cache_destroy(exception_cache); | 1475 | kmem_cache_destroy(exception_cache); |
| 1472 | kmem_cache_destroy(tracked_chunk_cache); | 1476 | kmem_cache_destroy(tracked_chunk_cache); |
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index 70dc961f40d8..292c15609ae3 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h | |||
| @@ -161,6 +161,8 @@ struct dm_snapshot { | |||
| 161 | /* The last percentage we notified */ | 161 | /* The last percentage we notified */ |
| 162 | int last_percent; | 162 | int last_percent; |
| 163 | 163 | ||
| 164 | mempool_t *pending_pool; | ||
| 165 | |||
| 164 | struct exception_table pending; | 166 | struct exception_table pending; |
| 165 | struct exception_table complete; | 167 | struct exception_table complete; |
| 166 | 168 | ||
