diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2008-04-24 16:43:49 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2008-04-25 08:26:52 -0400 |
commit | 945fa4d283a3a472186c11028f6fea1e77a91d14 (patch) | |
tree | 99af5b3623665680417a61a43f5effcfbeba903b | |
parent | 08d8757a4d52d21d825b9170af36f2696d1da1a8 (diff) |
dm kcopyd: remove redundant client counting
Remove client counting code that is no longer needed.
Initialization and destruction is made globally from dm_init and dm_exit and is
not based on client counts. Initialization allocates only one empty slab cache,
so there is no negative impact from performing the initialization always,
regardless of whether some client uses kcopyd or not.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm.c | 2 | ||||
-rw-r--r-- | drivers/md/dm.h | 3 | ||||
-rw-r--r-- | drivers/md/kcopyd.c | 122 |
3 files changed, 29 insertions, 98 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6617ce4af095..11f4ffedd646 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = { | |||
204 | dm_target_init, | 204 | dm_target_init, |
205 | dm_linear_init, | 205 | dm_linear_init, |
206 | dm_stripe_init, | 206 | dm_stripe_init, |
207 | dm_kcopyd_init, | ||
207 | dm_interface_init, | 208 | dm_interface_init, |
208 | }; | 209 | }; |
209 | 210 | ||
@@ -212,6 +213,7 @@ static void (*_exits[])(void) = { | |||
212 | dm_target_exit, | 213 | dm_target_exit, |
213 | dm_linear_exit, | 214 | dm_linear_exit, |
214 | dm_stripe_exit, | 215 | dm_stripe_exit, |
216 | dm_kcopyd_exit, | ||
215 | dm_interface_exit, | 217 | dm_interface_exit, |
216 | }; | 218 | }; |
217 | 219 | ||
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 17f2d6a8b124..9a6023c9bc6b 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -195,4 +195,7 @@ void dm_kobject_uevent(struct mapped_device *md); | |||
195 | int dm_dirty_log_init(void); | 195 | int dm_dirty_log_init(void); |
196 | void dm_dirty_log_exit(void); | 196 | void dm_dirty_log_exit(void); |
197 | 197 | ||
198 | int dm_kcopyd_init(void); | ||
199 | void dm_kcopyd_exit(void); | ||
200 | |||
198 | #endif | 201 | #endif |
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 0b2907d59a3f..17345844b03e 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c | |||
@@ -31,8 +31,6 @@ | |||
31 | * pages for kcopyd io. | 31 | * pages for kcopyd io. |
32 | *---------------------------------------------------------------*/ | 32 | *---------------------------------------------------------------*/ |
33 | struct dm_kcopyd_client { | 33 | struct dm_kcopyd_client { |
34 | struct list_head list; | ||
35 | |||
36 | spinlock_t lock; | 34 | spinlock_t lock; |
37 | struct page_list *pages; | 35 | struct page_list *pages; |
38 | unsigned int nr_pages; | 36 | unsigned int nr_pages; |
@@ -224,7 +222,7 @@ struct kcopyd_job { | |||
224 | 222 | ||
225 | static struct kmem_cache *_job_cache; | 223 | static struct kmem_cache *_job_cache; |
226 | 224 | ||
227 | static int jobs_init(void) | 225 | int __init dm_kcopyd_init(void) |
228 | { | 226 | { |
229 | _job_cache = KMEM_CACHE(kcopyd_job, 0); | 227 | _job_cache = KMEM_CACHE(kcopyd_job, 0); |
230 | if (!_job_cache) | 228 | if (!_job_cache) |
@@ -233,7 +231,7 @@ static int jobs_init(void) | |||
233 | return 0; | 231 | return 0; |
234 | } | 232 | } |
235 | 233 | ||
236 | static void jobs_exit(void) | 234 | void dm_kcopyd_exit(void) |
237 | { | 235 | { |
238 | kmem_cache_destroy(_job_cache); | 236 | kmem_cache_destroy(_job_cache); |
239 | _job_cache = NULL; | 237 | _job_cache = NULL; |
@@ -581,78 +579,17 @@ int kcopyd_cancel(struct kcopyd_job *job, int block) | |||
581 | #endif /* 0 */ | 579 | #endif /* 0 */ |
582 | 580 | ||
583 | /*----------------------------------------------------------------- | 581 | /*----------------------------------------------------------------- |
584 | * Unit setup | 582 | * Client setup |
585 | *---------------------------------------------------------------*/ | 583 | *---------------------------------------------------------------*/ |
586 | static DEFINE_MUTEX(_client_lock); | ||
587 | static LIST_HEAD(_clients); | ||
588 | |||
589 | static void client_add(struct dm_kcopyd_client *kc) | ||
590 | { | ||
591 | mutex_lock(&_client_lock); | ||
592 | list_add(&kc->list, &_clients); | ||
593 | mutex_unlock(&_client_lock); | ||
594 | } | ||
595 | |||
596 | static void client_del(struct dm_kcopyd_client *kc) | ||
597 | { | ||
598 | mutex_lock(&_client_lock); | ||
599 | list_del(&kc->list); | ||
600 | mutex_unlock(&_client_lock); | ||
601 | } | ||
602 | |||
603 | static DEFINE_MUTEX(kcopyd_init_lock); | ||
604 | static int kcopyd_clients = 0; | ||
605 | |||
606 | static int kcopyd_init(void) | ||
607 | { | ||
608 | int r; | ||
609 | |||
610 | mutex_lock(&kcopyd_init_lock); | ||
611 | |||
612 | if (kcopyd_clients) { | ||
613 | /* Already initialized. */ | ||
614 | kcopyd_clients++; | ||
615 | mutex_unlock(&kcopyd_init_lock); | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | r = jobs_init(); | ||
620 | if (r) { | ||
621 | mutex_unlock(&kcopyd_init_lock); | ||
622 | return r; | ||
623 | } | ||
624 | |||
625 | kcopyd_clients++; | ||
626 | mutex_unlock(&kcopyd_init_lock); | ||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static void kcopyd_exit(void) | ||
631 | { | ||
632 | mutex_lock(&kcopyd_init_lock); | ||
633 | kcopyd_clients--; | ||
634 | if (!kcopyd_clients) { | ||
635 | jobs_exit(); | ||
636 | } | ||
637 | mutex_unlock(&kcopyd_init_lock); | ||
638 | } | ||
639 | |||
640 | int dm_kcopyd_client_create(unsigned int nr_pages, | 584 | int dm_kcopyd_client_create(unsigned int nr_pages, |
641 | struct dm_kcopyd_client **result) | 585 | struct dm_kcopyd_client **result) |
642 | { | 586 | { |
643 | int r = 0; | 587 | int r = -ENOMEM; |
644 | struct dm_kcopyd_client *kc; | 588 | struct dm_kcopyd_client *kc; |
645 | 589 | ||
646 | r = kcopyd_init(); | ||
647 | if (r) | ||
648 | return r; | ||
649 | |||
650 | kc = kmalloc(sizeof(*kc), GFP_KERNEL); | 590 | kc = kmalloc(sizeof(*kc), GFP_KERNEL); |
651 | if (!kc) { | 591 | if (!kc) |
652 | r = -ENOMEM; | 592 | return -ENOMEM; |
653 | kcopyd_exit(); | ||
654 | return r; | ||
655 | } | ||
656 | 593 | ||
657 | spin_lock_init(&kc->lock); | 594 | spin_lock_init(&kc->lock); |
658 | spin_lock_init(&kc->job_lock); | 595 | spin_lock_init(&kc->job_lock); |
@@ -661,51 +598,42 @@ int dm_kcopyd_client_create(unsigned int nr_pages, | |||
661 | INIT_LIST_HEAD(&kc->pages_jobs); | 598 | INIT_LIST_HEAD(&kc->pages_jobs); |
662 | 599 | ||
663 | kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache); | 600 | kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache); |
664 | if (!kc->job_pool) { | 601 | if (!kc->job_pool) |
665 | r = -ENOMEM; | 602 | goto bad_slab; |
666 | kfree(kc); | ||
667 | kcopyd_exit(); | ||
668 | return r; | ||
669 | } | ||
670 | 603 | ||
671 | INIT_WORK(&kc->kcopyd_work, do_work); | 604 | INIT_WORK(&kc->kcopyd_work, do_work); |
672 | kc->kcopyd_wq = create_singlethread_workqueue("kcopyd"); | 605 | kc->kcopyd_wq = create_singlethread_workqueue("kcopyd"); |
673 | if (!kc->kcopyd_wq) { | 606 | if (!kc->kcopyd_wq) |
674 | r = -ENOMEM; | 607 | goto bad_workqueue; |
675 | mempool_destroy(kc->job_pool); | ||
676 | kfree(kc); | ||
677 | kcopyd_exit(); | ||
678 | return r; | ||
679 | } | ||
680 | 608 | ||
681 | kc->pages = NULL; | 609 | kc->pages = NULL; |
682 | kc->nr_pages = kc->nr_free_pages = 0; | 610 | kc->nr_pages = kc->nr_free_pages = 0; |
683 | r = client_alloc_pages(kc, nr_pages); | 611 | r = client_alloc_pages(kc, nr_pages); |
684 | if (r) { | 612 | if (r) |
685 | destroy_workqueue(kc->kcopyd_wq); | 613 | goto bad_client_pages; |
686 | mempool_destroy(kc->job_pool); | ||
687 | kfree(kc); | ||
688 | kcopyd_exit(); | ||
689 | return r; | ||
690 | } | ||
691 | 614 | ||
692 | kc->io_client = dm_io_client_create(nr_pages); | 615 | kc->io_client = dm_io_client_create(nr_pages); |
693 | if (IS_ERR(kc->io_client)) { | 616 | if (IS_ERR(kc->io_client)) { |
694 | r = PTR_ERR(kc->io_client); | 617 | r = PTR_ERR(kc->io_client); |
695 | client_free_pages(kc); | 618 | goto bad_io_client; |
696 | destroy_workqueue(kc->kcopyd_wq); | ||
697 | mempool_destroy(kc->job_pool); | ||
698 | kfree(kc); | ||
699 | kcopyd_exit(); | ||
700 | return r; | ||
701 | } | 619 | } |
702 | 620 | ||
703 | init_waitqueue_head(&kc->destroyq); | 621 | init_waitqueue_head(&kc->destroyq); |
704 | atomic_set(&kc->nr_jobs, 0); | 622 | atomic_set(&kc->nr_jobs, 0); |
705 | 623 | ||
706 | client_add(kc); | ||
707 | *result = kc; | 624 | *result = kc; |
708 | return 0; | 625 | return 0; |
626 | |||
627 | bad_io_client: | ||
628 | client_free_pages(kc); | ||
629 | bad_client_pages: | ||
630 | destroy_workqueue(kc->kcopyd_wq); | ||
631 | bad_workqueue: | ||
632 | mempool_destroy(kc->job_pool); | ||
633 | bad_slab: | ||
634 | kfree(kc); | ||
635 | |||
636 | return r; | ||
709 | } | 637 | } |
710 | EXPORT_SYMBOL(dm_kcopyd_client_create); | 638 | EXPORT_SYMBOL(dm_kcopyd_client_create); |
711 | 639 | ||
@@ -720,9 +648,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc) | |||
720 | destroy_workqueue(kc->kcopyd_wq); | 648 | destroy_workqueue(kc->kcopyd_wq); |
721 | dm_io_client_destroy(kc->io_client); | 649 | dm_io_client_destroy(kc->io_client); |
722 | client_free_pages(kc); | 650 | client_free_pages(kc); |
723 | client_del(kc); | ||
724 | mempool_destroy(kc->job_pool); | 651 | mempool_destroy(kc->job_pool); |
725 | kfree(kc); | 652 | kfree(kc); |
726 | kcopyd_exit(); | ||
727 | } | 653 | } |
728 | EXPORT_SYMBOL(dm_kcopyd_client_destroy); | 654 | EXPORT_SYMBOL(dm_kcopyd_client_destroy); |