diff options
Diffstat (limited to 'drivers/md')
-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 = { dm_target_init, dm_linear_init, dm_stripe_init, + dm_kcopyd_init, dm_interface_init, }; @@ -212,6 +213,7 @@ static void (*_exits[])(void) = { dm_target_exit, dm_linear_exit, dm_stripe_exit, + dm_kcopyd_exit, dm_interface_exit, }; 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); int dm_dirty_log_init(void); void dm_dirty_log_exit(void); +int dm_kcopyd_init(void); +void dm_kcopyd_exit(void); + #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 @@ * pages for kcopyd io. *---------------------------------------------------------------*/ struct dm_kcopyd_client { - struct list_head list; - spinlock_t lock; struct page_list *pages; unsigned int nr_pages; @@ -224,7 +222,7 @@ struct kcopyd_job { static struct kmem_cache *_job_cache; -static int jobs_init(void) +int __init dm_kcopyd_init(void) { _job_cache = KMEM_CACHE(kcopyd_job, 0); if (!_job_cache) @@ -233,7 +231,7 @@ static int jobs_init(void) return 0; } -static void jobs_exit(void) +void dm_kcopyd_exit(void) { kmem_cache_destroy(_job_cache); _job_cache = NULL; @@ -581,78 +579,17 @@ int kcopyd_cancel(struct kcopyd_job *job, int block) #endif /* 0 */ /*----------------------------------------------------------------- - * Unit setup + * Client setup *---------------------------------------------------------------*/ -static DEFINE_MUTEX(_client_lock); -static LIST_HEAD(_clients); - -static void client_add(struct dm_kcopyd_client *kc) -{ - mutex_lock(&_client_lock); - list_add(&kc->list, &_clients); - mutex_unlock(&_client_lock); -} - -static void client_del(struct dm_kcopyd_client *kc) -{ - mutex_lock(&_client_lock); - list_del(&kc->list); - mutex_unlock(&_client_lock); -} - -static DEFINE_MUTEX(kcopyd_init_lock); -static int kcopyd_clients = 0; - -static int kcopyd_init(void) -{ - int r; - - mutex_lock(&kcopyd_init_lock); - - if (kcopyd_clients) { - /* Already initialized. */ - kcopyd_clients++; - mutex_unlock(&kcopyd_init_lock); - return 0; - } - - r = jobs_init(); - if (r) { - mutex_unlock(&kcopyd_init_lock); - return r; - } - - kcopyd_clients++; - mutex_unlock(&kcopyd_init_lock); - return 0; -} - -static void kcopyd_exit(void) -{ - mutex_lock(&kcopyd_init_lock); - kcopyd_clients--; - if (!kcopyd_clients) { - jobs_exit(); - } - mutex_unlock(&kcopyd_init_lock); -} - int dm_kcopyd_client_create(unsigned int nr_pages, struct dm_kcopyd_client **result) { - int r = 0; + int r = -ENOMEM; struct dm_kcopyd_client *kc; - r = kcopyd_init(); - if (r) - return r; - kc = kmalloc(sizeof(*kc), GFP_KERNEL); - if (!kc) { - r = -ENOMEM; - kcopyd_exit(); - return r; - } + if (!kc) + return -ENOMEM; spin_lock_init(&kc->lock); spin_lock_init(&kc->job_lock); @@ -661,51 +598,42 @@ int dm_kcopyd_client_create(unsigned int nr_pages, INIT_LIST_HEAD(&kc->pages_jobs); kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache); - if (!kc->job_pool) { - r = -ENOMEM; - kfree(kc); - kcopyd_exit(); - return r; - } + if (!kc->job_pool) + goto bad_slab; INIT_WORK(&kc->kcopyd_work, do_work); kc->kcopyd_wq = create_singlethread_workqueue("kcopyd"); - if (!kc->kcopyd_wq) { - r = -ENOMEM; - mempool_destroy(kc->job_pool); - kfree(kc); - kcopyd_exit(); - return r; - } + if (!kc->kcopyd_wq) + goto bad_workqueue; kc->pages = NULL; kc->nr_pages = kc->nr_free_pages = 0; r = client_alloc_pages(kc, nr_pages); - if (r) { - destroy_workqueue(kc->kcopyd_wq); - mempool_destroy(kc->job_pool); - kfree(kc); - kcopyd_exit(); - return r; - } + if (r) + goto bad_client_pages; kc->io_client = dm_io_client_create(nr_pages); if (IS_ERR(kc->io_client)) { r = PTR_ERR(kc->io_client); - client_free_pages(kc); - destroy_workqueue(kc->kcopyd_wq); - mempool_destroy(kc->job_pool); - kfree(kc); - kcopyd_exit(); - return r; + goto bad_io_client; } init_waitqueue_head(&kc->destroyq); atomic_set(&kc->nr_jobs, 0); - client_add(kc); *result = kc; return 0; + +bad_io_client: + client_free_pages(kc); +bad_client_pages: + destroy_workqueue(kc->kcopyd_wq); +bad_workqueue: + mempool_destroy(kc->job_pool); +bad_slab: + kfree(kc); + + return r; } EXPORT_SYMBOL(dm_kcopyd_client_create); @@ -720,9 +648,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc) destroy_workqueue(kc->kcopyd_wq); dm_io_client_destroy(kc->io_client); client_free_pages(kc); - client_del(kc); mempool_destroy(kc->job_pool); kfree(kc); - kcopyd_exit(); } EXPORT_SYMBOL(dm_kcopyd_client_destroy); |