aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/kcopyd.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2008-04-24 16:43:49 -0400
committerAlasdair G Kergon <agk@redhat.com>2008-04-25 08:26:52 -0400
commit945fa4d283a3a472186c11028f6fea1e77a91d14 (patch)
tree99af5b3623665680417a61a43f5effcfbeba903b /drivers/md/kcopyd.c
parent08d8757a4d52d21d825b9170af36f2696d1da1a8 (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>
Diffstat (limited to 'drivers/md/kcopyd.c')
-rw-r--r--drivers/md/kcopyd.c122
1 files changed, 24 insertions, 98 deletions
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 *---------------------------------------------------------------*/
33struct dm_kcopyd_client { 33struct 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
225static struct kmem_cache *_job_cache; 223static struct kmem_cache *_job_cache;
226 224
227static int jobs_init(void) 225int __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
236static void jobs_exit(void) 234void 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 *---------------------------------------------------------------*/
586static DEFINE_MUTEX(_client_lock);
587static LIST_HEAD(_clients);
588
589static 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
596static 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
603static DEFINE_MUTEX(kcopyd_init_lock);
604static int kcopyd_clients = 0;
605
606static 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
630static 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
640int dm_kcopyd_client_create(unsigned int nr_pages, 584int 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
627bad_io_client:
628 client_free_pages(kc);
629bad_client_pages:
630 destroy_workqueue(kc->kcopyd_wq);
631bad_workqueue:
632 mempool_destroy(kc->job_pool);
633bad_slab:
634 kfree(kc);
635
636 return r;
709} 637}
710EXPORT_SYMBOL(dm_kcopyd_client_create); 638EXPORT_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}
728EXPORT_SYMBOL(dm_kcopyd_client_destroy); 654EXPORT_SYMBOL(dm_kcopyd_client_destroy);