Commit 08d8757a authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Alasdair G Kergon

dm kcopyd: private mempool

Change the global mempool in kcopyd into a per-device mempool to avoid
deadlock possibilities.
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 8c0cbc2f
...@@ -43,6 +43,8 @@ struct dm_kcopyd_client { ...@@ -43,6 +43,8 @@ struct dm_kcopyd_client {
wait_queue_head_t destroyq; wait_queue_head_t destroyq;
atomic_t nr_jobs; atomic_t nr_jobs;
mempool_t *job_pool;
struct workqueue_struct *kcopyd_wq; struct workqueue_struct *kcopyd_wq;
struct work_struct kcopyd_work; struct work_struct kcopyd_work;
...@@ -221,7 +223,6 @@ struct kcopyd_job { ...@@ -221,7 +223,6 @@ struct kcopyd_job {
#define MIN_JOBS 512 #define MIN_JOBS 512
static struct kmem_cache *_job_cache; static struct kmem_cache *_job_cache;
static mempool_t *_job_pool;
static int jobs_init(void) static int jobs_init(void)
{ {
...@@ -229,20 +230,12 @@ static int jobs_init(void) ...@@ -229,20 +230,12 @@ static int jobs_init(void)
if (!_job_cache) if (!_job_cache)
return -ENOMEM; return -ENOMEM;
_job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
if (!_job_pool) {
kmem_cache_destroy(_job_cache);
return -ENOMEM;
}
return 0; return 0;
} }
static void jobs_exit(void) static void jobs_exit(void)
{ {
mempool_destroy(_job_pool);
kmem_cache_destroy(_job_cache); kmem_cache_destroy(_job_cache);
_job_pool = NULL;
_job_cache = NULL; _job_cache = NULL;
} }
...@@ -295,7 +288,7 @@ static int run_complete_job(struct kcopyd_job *job) ...@@ -295,7 +288,7 @@ static int run_complete_job(struct kcopyd_job *job)
struct dm_kcopyd_client *kc = job->kc; struct dm_kcopyd_client *kc = job->kc;
kcopyd_put_pages(kc, job->pages); kcopyd_put_pages(kc, job->pages);
mempool_free(job, _job_pool); mempool_free(job, kc->job_pool);
fn(read_err, write_err, context); fn(read_err, write_err, context);
if (atomic_dec_and_test(&kc->nr_jobs)) if (atomic_dec_and_test(&kc->nr_jobs))
...@@ -487,7 +480,8 @@ static void segment_complete(int read_err, unsigned long write_err, ...@@ -487,7 +480,8 @@ static void segment_complete(int read_err, unsigned long write_err,
if (count) { if (count) {
int i; int i;
struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO); struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
GFP_NOIO);
*sub_job = *job; *sub_job = *job;
sub_job->source.sector += progress; sub_job->source.sector += progress;
...@@ -511,7 +505,7 @@ static void segment_complete(int read_err, unsigned long write_err, ...@@ -511,7 +505,7 @@ static void segment_complete(int read_err, unsigned long write_err,
* after we've completed. * after we've completed.
*/ */
job->fn(read_err, write_err, job->context); job->fn(read_err, write_err, job->context);
mempool_free(job, _job_pool); mempool_free(job, job->kc->job_pool);
} }
} }
...@@ -538,7 +532,7 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, ...@@ -538,7 +532,7 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
/* /*
* Allocate a new job. * Allocate a new job.
*/ */
job = mempool_alloc(_job_pool, GFP_NOIO); job = mempool_alloc(kc->job_pool, GFP_NOIO);
/* /*
* set up for the read. * set up for the read.
...@@ -666,10 +660,19 @@ int dm_kcopyd_client_create(unsigned int nr_pages, ...@@ -666,10 +660,19 @@ int dm_kcopyd_client_create(unsigned int nr_pages,
INIT_LIST_HEAD(&kc->io_jobs); INIT_LIST_HEAD(&kc->io_jobs);
INIT_LIST_HEAD(&kc->pages_jobs); 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;
}
INIT_WORK(&kc->kcopyd_work, do_work); INIT_WORK(&kc->kcopyd_work, do_work);
kc->kcopyd_wq = create_singlethread_workqueue("kcopyd"); kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
if (!kc->kcopyd_wq) { if (!kc->kcopyd_wq) {
r = -ENOMEM; r = -ENOMEM;
mempool_destroy(kc->job_pool);
kfree(kc); kfree(kc);
kcopyd_exit(); kcopyd_exit();
return r; return r;
...@@ -680,6 +683,7 @@ int dm_kcopyd_client_create(unsigned int nr_pages, ...@@ -680,6 +683,7 @@ int dm_kcopyd_client_create(unsigned int nr_pages,
r = client_alloc_pages(kc, nr_pages); r = client_alloc_pages(kc, nr_pages);
if (r) { if (r) {
destroy_workqueue(kc->kcopyd_wq); destroy_workqueue(kc->kcopyd_wq);
mempool_destroy(kc->job_pool);
kfree(kc); kfree(kc);
kcopyd_exit(); kcopyd_exit();
return r; return r;
...@@ -690,6 +694,7 @@ int dm_kcopyd_client_create(unsigned int nr_pages, ...@@ -690,6 +694,7 @@ int dm_kcopyd_client_create(unsigned int nr_pages,
r = PTR_ERR(kc->io_client); r = PTR_ERR(kc->io_client);
client_free_pages(kc); client_free_pages(kc);
destroy_workqueue(kc->kcopyd_wq); destroy_workqueue(kc->kcopyd_wq);
mempool_destroy(kc->job_pool);
kfree(kc); kfree(kc);
kcopyd_exit(); kcopyd_exit();
return r; return r;
...@@ -716,6 +721,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc) ...@@ -716,6 +721,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
dm_io_client_destroy(kc->io_client); dm_io_client_destroy(kc->io_client);
client_free_pages(kc); client_free_pages(kc);
client_del(kc); client_del(kc);
mempool_destroy(kc->job_pool);
kfree(kc); kfree(kc);
kcopyd_exit(); kcopyd_exit();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment