aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-kcopyd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-kcopyd.c')
-rw-r--r--drivers/md/dm-kcopyd.c176
1 files changed, 104 insertions, 72 deletions
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index d8587bac5682..819e37eaaeba 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -27,15 +27,19 @@
27 27
28#include "dm.h" 28#include "dm.h"
29 29
30#define SUB_JOB_SIZE 128
31#define SPLIT_COUNT 8
32#define MIN_JOBS 8
33#define RESERVE_PAGES (DIV_ROUND_UP(SUB_JOB_SIZE << SECTOR_SHIFT, PAGE_SIZE))
34
30/*----------------------------------------------------------------- 35/*-----------------------------------------------------------------
31 * Each kcopyd client has its own little pool of preallocated 36 * Each kcopyd client has its own little pool of preallocated
32 * pages for kcopyd io. 37 * pages for kcopyd io.
33 *---------------------------------------------------------------*/ 38 *---------------------------------------------------------------*/
34struct dm_kcopyd_client { 39struct dm_kcopyd_client {
35 spinlock_t lock;
36 struct page_list *pages; 40 struct page_list *pages;
37 unsigned int nr_pages; 41 unsigned nr_reserved_pages;
38 unsigned int nr_free_pages; 42 unsigned nr_free_pages;
39 43
40 struct dm_io_client *io_client; 44 struct dm_io_client *io_client;
41 45
@@ -67,15 +71,18 @@ static void wake(struct dm_kcopyd_client *kc)
67 queue_work(kc->kcopyd_wq, &kc->kcopyd_work); 71 queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
68} 72}
69 73
70static struct page_list *alloc_pl(void) 74/*
75 * Obtain one page for the use of kcopyd.
76 */
77static struct page_list *alloc_pl(gfp_t gfp)
71{ 78{
72 struct page_list *pl; 79 struct page_list *pl;
73 80
74 pl = kmalloc(sizeof(*pl), GFP_KERNEL); 81 pl = kmalloc(sizeof(*pl), gfp);
75 if (!pl) 82 if (!pl)
76 return NULL; 83 return NULL;
77 84
78 pl->page = alloc_page(GFP_KERNEL); 85 pl->page = alloc_page(gfp);
79 if (!pl->page) { 86 if (!pl->page) {
80 kfree(pl); 87 kfree(pl);
81 return NULL; 88 return NULL;
@@ -90,41 +97,56 @@ static void free_pl(struct page_list *pl)
90 kfree(pl); 97 kfree(pl);
91} 98}
92 99
93static int kcopyd_get_pages(struct dm_kcopyd_client *kc, 100/*
94 unsigned int nr, struct page_list **pages) 101 * Add the provided pages to a client's free page list, releasing
102 * back to the system any beyond the reserved_pages limit.
103 */
104static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
95{ 105{
96 struct page_list *pl; 106 struct page_list *next;
97
98 spin_lock(&kc->lock);
99 if (kc->nr_free_pages < nr) {
100 spin_unlock(&kc->lock);
101 return -ENOMEM;
102 }
103
104 kc->nr_free_pages -= nr;
105 for (*pages = pl = kc->pages; --nr; pl = pl->next)
106 ;
107 107
108 kc->pages = pl->next; 108 do {
109 pl->next = NULL; 109 next = pl->next;
110 110
111 spin_unlock(&kc->lock); 111 if (kc->nr_free_pages >= kc->nr_reserved_pages)
112 free_pl(pl);
113 else {
114 pl->next = kc->pages;
115 kc->pages = pl;
116 kc->nr_free_pages++;
117 }
112 118
113 return 0; 119 pl = next;
120 } while (pl);
114} 121}
115 122
116static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl) 123static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
124 unsigned int nr, struct page_list **pages)
117{ 125{
118 struct page_list *cursor; 126 struct page_list *pl;
127
128 *pages = NULL;
129
130 do {
131 pl = alloc_pl(__GFP_NOWARN | __GFP_NORETRY);
132 if (unlikely(!pl)) {
133 /* Use reserved pages */
134 pl = kc->pages;
135 if (unlikely(!pl))
136 goto out_of_memory;
137 kc->pages = pl->next;
138 kc->nr_free_pages--;
139 }
140 pl->next = *pages;
141 *pages = pl;
142 } while (--nr);
119 143
120 spin_lock(&kc->lock); 144 return 0;
121 for (cursor = pl; cursor->next; cursor = cursor->next)
122 kc->nr_free_pages++;
123 145
124 kc->nr_free_pages++; 146out_of_memory:
125 cursor->next = kc->pages; 147 if (*pages)
126 kc->pages = pl; 148 kcopyd_put_pages(kc, *pages);
127 spin_unlock(&kc->lock); 149 return -ENOMEM;
128} 150}
129 151
130/* 152/*
@@ -141,13 +163,16 @@ static void drop_pages(struct page_list *pl)
141 } 163 }
142} 164}
143 165
144static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr) 166/*
167 * Allocate and reserve nr_pages for the use of a specific client.
168 */
169static int client_reserve_pages(struct dm_kcopyd_client *kc, unsigned nr_pages)
145{ 170{
146 unsigned int i; 171 unsigned i;
147 struct page_list *pl = NULL, *next; 172 struct page_list *pl = NULL, *next;
148 173
149 for (i = 0; i < nr; i++) { 174 for (i = 0; i < nr_pages; i++) {
150 next = alloc_pl(); 175 next = alloc_pl(GFP_KERNEL);
151 if (!next) { 176 if (!next) {
152 if (pl) 177 if (pl)
153 drop_pages(pl); 178 drop_pages(pl);
@@ -157,17 +182,18 @@ static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr)
157 pl = next; 182 pl = next;
158 } 183 }
159 184
185 kc->nr_reserved_pages += nr_pages;
160 kcopyd_put_pages(kc, pl); 186 kcopyd_put_pages(kc, pl);
161 kc->nr_pages += nr; 187
162 return 0; 188 return 0;
163} 189}
164 190
165static void client_free_pages(struct dm_kcopyd_client *kc) 191static void client_free_pages(struct dm_kcopyd_client *kc)
166{ 192{
167 BUG_ON(kc->nr_free_pages != kc->nr_pages); 193 BUG_ON(kc->nr_free_pages != kc->nr_reserved_pages);
168 drop_pages(kc->pages); 194 drop_pages(kc->pages);
169 kc->pages = NULL; 195 kc->pages = NULL;
170 kc->nr_free_pages = kc->nr_pages = 0; 196 kc->nr_free_pages = kc->nr_reserved_pages = 0;
171} 197}
172 198
173/*----------------------------------------------------------------- 199/*-----------------------------------------------------------------
@@ -216,16 +242,17 @@ struct kcopyd_job {
216 struct mutex lock; 242 struct mutex lock;
217 atomic_t sub_jobs; 243 atomic_t sub_jobs;
218 sector_t progress; 244 sector_t progress;
219};
220 245
221/* FIXME: this should scale with the number of pages */ 246 struct kcopyd_job *master_job;
222#define MIN_JOBS 512 247};
223 248
224static struct kmem_cache *_job_cache; 249static struct kmem_cache *_job_cache;
225 250
226int __init dm_kcopyd_init(void) 251int __init dm_kcopyd_init(void)
227{ 252{
228 _job_cache = KMEM_CACHE(kcopyd_job, 0); 253 _job_cache = kmem_cache_create("kcopyd_job",
254 sizeof(struct kcopyd_job) * (SPLIT_COUNT + 1),
255 __alignof__(struct kcopyd_job), 0, NULL);
229 if (!_job_cache) 256 if (!_job_cache)
230 return -ENOMEM; 257 return -ENOMEM;
231 258
@@ -299,7 +326,12 @@ static int run_complete_job(struct kcopyd_job *job)
299 326
300 if (job->pages) 327 if (job->pages)
301 kcopyd_put_pages(kc, job->pages); 328 kcopyd_put_pages(kc, job->pages);
302 mempool_free(job, kc->job_pool); 329 /*
330 * If this is the master job, the sub jobs have already
331 * completed so we can free everything.
332 */
333 if (job->master_job == job)
334 mempool_free(job, kc->job_pool);
303 fn(read_err, write_err, context); 335 fn(read_err, write_err, context);
304 336
305 if (atomic_dec_and_test(&kc->nr_jobs)) 337 if (atomic_dec_and_test(&kc->nr_jobs))
@@ -345,7 +377,7 @@ static int run_io_job(struct kcopyd_job *job)
345{ 377{
346 int r; 378 int r;
347 struct dm_io_request io_req = { 379 struct dm_io_request io_req = {
348 .bi_rw = job->rw | REQ_SYNC | REQ_UNPLUG, 380 .bi_rw = job->rw,
349 .mem.type = DM_IO_PAGE_LIST, 381 .mem.type = DM_IO_PAGE_LIST,
350 .mem.ptr.pl = job->pages, 382 .mem.ptr.pl = job->pages,
351 .mem.offset = job->offset, 383 .mem.offset = job->offset,
@@ -428,6 +460,7 @@ static void do_work(struct work_struct *work)
428{ 460{
429 struct dm_kcopyd_client *kc = container_of(work, 461 struct dm_kcopyd_client *kc = container_of(work,
430 struct dm_kcopyd_client, kcopyd_work); 462 struct dm_kcopyd_client, kcopyd_work);
463 struct blk_plug plug;
431 464
432 /* 465 /*
433 * The order that these are called is *very* important. 466 * The order that these are called is *very* important.
@@ -436,9 +469,11 @@ static void do_work(struct work_struct *work)
436 * list. io jobs call wake when they complete and it all 469 * list. io jobs call wake when they complete and it all
437 * starts again. 470 * starts again.
438 */ 471 */
472 blk_start_plug(&plug);
439 process_jobs(&kc->complete_jobs, kc, run_complete_job); 473 process_jobs(&kc->complete_jobs, kc, run_complete_job);
440 process_jobs(&kc->pages_jobs, kc, run_pages_job); 474 process_jobs(&kc->pages_jobs, kc, run_pages_job);
441 process_jobs(&kc->io_jobs, kc, run_io_job); 475 process_jobs(&kc->io_jobs, kc, run_io_job);
476 blk_finish_plug(&plug);
442} 477}
443 478
444/* 479/*
@@ -457,14 +492,14 @@ static void dispatch_job(struct kcopyd_job *job)
457 wake(kc); 492 wake(kc);
458} 493}
459 494
460#define SUB_JOB_SIZE 128
461static void segment_complete(int read_err, unsigned long write_err, 495static void segment_complete(int read_err, unsigned long write_err,
462 void *context) 496 void *context)
463{ 497{
464 /* FIXME: tidy this function */ 498 /* FIXME: tidy this function */
465 sector_t progress = 0; 499 sector_t progress = 0;
466 sector_t count = 0; 500 sector_t count = 0;
467 struct kcopyd_job *job = (struct kcopyd_job *) context; 501 struct kcopyd_job *sub_job = (struct kcopyd_job *) context;
502 struct kcopyd_job *job = sub_job->master_job;
468 struct dm_kcopyd_client *kc = job->kc; 503 struct dm_kcopyd_client *kc = job->kc;
469 504
470 mutex_lock(&job->lock); 505 mutex_lock(&job->lock);
@@ -495,8 +530,6 @@ static void segment_complete(int read_err, unsigned long write_err,
495 530
496 if (count) { 531 if (count) {
497 int i; 532 int i;
498 struct kcopyd_job *sub_job = mempool_alloc(kc->job_pool,
499 GFP_NOIO);
500 533
501 *sub_job = *job; 534 *sub_job = *job;
502 sub_job->source.sector += progress; 535 sub_job->source.sector += progress;
@@ -508,7 +541,7 @@ static void segment_complete(int read_err, unsigned long write_err,
508 } 541 }
509 542
510 sub_job->fn = segment_complete; 543 sub_job->fn = segment_complete;
511 sub_job->context = job; 544 sub_job->context = sub_job;
512 dispatch_job(sub_job); 545 dispatch_job(sub_job);
513 546
514 } else if (atomic_dec_and_test(&job->sub_jobs)) { 547 } else if (atomic_dec_and_test(&job->sub_jobs)) {
@@ -528,19 +561,19 @@ static void segment_complete(int read_err, unsigned long write_err,
528} 561}
529 562
530/* 563/*
531 * Create some little jobs that will do the move between 564 * Create some sub jobs to share the work between them.
532 * them.
533 */ 565 */
534#define SPLIT_COUNT 8 566static void split_job(struct kcopyd_job *master_job)
535static void split_job(struct kcopyd_job *job)
536{ 567{
537 int i; 568 int i;
538 569
539 atomic_inc(&job->kc->nr_jobs); 570 atomic_inc(&master_job->kc->nr_jobs);
540 571
541 atomic_set(&job->sub_jobs, SPLIT_COUNT); 572 atomic_set(&master_job->sub_jobs, SPLIT_COUNT);
542 for (i = 0; i < SPLIT_COUNT; i++) 573 for (i = 0; i < SPLIT_COUNT; i++) {
543 segment_complete(0, 0u, job); 574 master_job[i + 1].master_job = master_job;
575 segment_complete(0, 0u, &master_job[i + 1]);
576 }
544} 577}
545 578
546int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, 579int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
@@ -550,7 +583,8 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
550 struct kcopyd_job *job; 583 struct kcopyd_job *job;
551 584
552 /* 585 /*
553 * Allocate a new job. 586 * Allocate an array of jobs consisting of one master job
587 * followed by SPLIT_COUNT sub jobs.
554 */ 588 */
555 job = mempool_alloc(kc->job_pool, GFP_NOIO); 589 job = mempool_alloc(kc->job_pool, GFP_NOIO);
556 590
@@ -574,10 +608,10 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
574 608
575 job->fn = fn; 609 job->fn = fn;
576 job->context = context; 610 job->context = context;
611 job->master_job = job;
577 612
578 if (job->source.count < SUB_JOB_SIZE) 613 if (job->source.count <= SUB_JOB_SIZE)
579 dispatch_job(job); 614 dispatch_job(job);
580
581 else { 615 else {
582 mutex_init(&job->lock); 616 mutex_init(&job->lock);
583 job->progress = 0; 617 job->progress = 0;
@@ -603,17 +637,15 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
603/*----------------------------------------------------------------- 637/*-----------------------------------------------------------------
604 * Client setup 638 * Client setup
605 *---------------------------------------------------------------*/ 639 *---------------------------------------------------------------*/
606int dm_kcopyd_client_create(unsigned int nr_pages, 640struct dm_kcopyd_client *dm_kcopyd_client_create(void)
607 struct dm_kcopyd_client **result)
608{ 641{
609 int r = -ENOMEM; 642 int r = -ENOMEM;
610 struct dm_kcopyd_client *kc; 643 struct dm_kcopyd_client *kc;
611 644
612 kc = kmalloc(sizeof(*kc), GFP_KERNEL); 645 kc = kmalloc(sizeof(*kc), GFP_KERNEL);
613 if (!kc) 646 if (!kc)
614 return -ENOMEM; 647 return ERR_PTR(-ENOMEM);
615 648
616 spin_lock_init(&kc->lock);
617 spin_lock_init(&kc->job_lock); 649 spin_lock_init(&kc->job_lock);
618 INIT_LIST_HEAD(&kc->complete_jobs); 650 INIT_LIST_HEAD(&kc->complete_jobs);
619 INIT_LIST_HEAD(&kc->io_jobs); 651 INIT_LIST_HEAD(&kc->io_jobs);
@@ -624,17 +656,18 @@ int dm_kcopyd_client_create(unsigned int nr_pages,
624 goto bad_slab; 656 goto bad_slab;
625 657
626 INIT_WORK(&kc->kcopyd_work, do_work); 658 INIT_WORK(&kc->kcopyd_work, do_work);
627 kc->kcopyd_wq = create_singlethread_workqueue("kcopyd"); 659 kc->kcopyd_wq = alloc_workqueue("kcopyd",
660 WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
628 if (!kc->kcopyd_wq) 661 if (!kc->kcopyd_wq)
629 goto bad_workqueue; 662 goto bad_workqueue;
630 663
631 kc->pages = NULL; 664 kc->pages = NULL;
632 kc->nr_pages = kc->nr_free_pages = 0; 665 kc->nr_reserved_pages = kc->nr_free_pages = 0;
633 r = client_alloc_pages(kc, nr_pages); 666 r = client_reserve_pages(kc, RESERVE_PAGES);
634 if (r) 667 if (r)
635 goto bad_client_pages; 668 goto bad_client_pages;
636 669
637 kc->io_client = dm_io_client_create(nr_pages); 670 kc->io_client = dm_io_client_create();
638 if (IS_ERR(kc->io_client)) { 671 if (IS_ERR(kc->io_client)) {
639 r = PTR_ERR(kc->io_client); 672 r = PTR_ERR(kc->io_client);
640 goto bad_io_client; 673 goto bad_io_client;
@@ -643,8 +676,7 @@ int dm_kcopyd_client_create(unsigned int nr_pages,
643 init_waitqueue_head(&kc->destroyq); 676 init_waitqueue_head(&kc->destroyq);
644 atomic_set(&kc->nr_jobs, 0); 677 atomic_set(&kc->nr_jobs, 0);
645 678
646 *result = kc; 679 return kc;
647 return 0;
648 680
649bad_io_client: 681bad_io_client:
650 client_free_pages(kc); 682 client_free_pages(kc);
@@ -655,7 +687,7 @@ bad_workqueue:
655bad_slab: 687bad_slab:
656 kfree(kc); 688 kfree(kc);
657 689
658 return r; 690 return ERR_PTR(r);
659} 691}
660EXPORT_SYMBOL(dm_kcopyd_client_create); 692EXPORT_SYMBOL(dm_kcopyd_client_create);
661 693