From c867056715b9664a35d324603385b1a7f639cfc8 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 31 Oct 2011 20:18:58 +0000 Subject: [PATCH] --- yaml --- r: 273315 b: refs/heads/master c: 7f06965390e4a10fb6906c886324bfd0a96961be h: refs/heads/master i: 273313: 66dec0c5583159bd828b01ba16dba2917a6669ce 273311: b03265b10426e3482ade91ac94c1a7070422c03e v: v3 --- [refs] | 2 +- trunk/drivers/md/dm-kcopyd.c | 31 ++++++++++++++++++++++++++----- trunk/include/linux/dm-kcopyd.h | 4 ++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index f461e75b0290..988bded368ae 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: fbdc86f3bd597e108fa03d998132d04fcfe1d669 +refs/heads/master: 7f06965390e4a10fb6906c886324bfd0a96961be diff --git a/trunk/drivers/md/dm-kcopyd.c b/trunk/drivers/md/dm-kcopyd.c index 32ac70861d66..bed444c93d8d 100644 --- a/trunk/drivers/md/dm-kcopyd.c +++ b/trunk/drivers/md/dm-kcopyd.c @@ -66,6 +66,8 @@ struct dm_kcopyd_client { struct list_head pages_jobs; }; +static struct page_list zero_page_list; + static void wake(struct dm_kcopyd_client *kc) { queue_work(kc->kcopyd_wq, &kc->kcopyd_work); @@ -254,6 +256,9 @@ int __init dm_kcopyd_init(void) if (!_job_cache) return -ENOMEM; + zero_page_list.next = &zero_page_list; + zero_page_list.page = ZERO_PAGE(0); + return 0; } @@ -322,7 +327,7 @@ static int run_complete_job(struct kcopyd_job *job) dm_kcopyd_notify_fn fn = job->fn; struct dm_kcopyd_client *kc = job->kc; - if (job->pages) + if (job->pages && job->pages != &zero_page_list) kcopyd_put_pages(kc, job->pages); /* * If this is the master job, the sub jobs have already @@ -484,6 +489,8 @@ static void dispatch_job(struct kcopyd_job *job) atomic_inc(&kc->nr_jobs); if (unlikely(!job->source.count)) push(&kc->complete_jobs, job); + else if (job->pages == &zero_page_list) + push(&kc->io_jobs, job); else push(&kc->pages_jobs, job); wake(kc); @@ -592,14 +599,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, job->flags = flags; job->read_err = 0; job->write_err = 0; - job->rw = READ; - - job->source = *from; job->num_dests = num_dests; memcpy(&job->dests, dests, sizeof(*dests) * num_dests); - job->pages = NULL; + if (from) { + job->source = *from; + job->pages = NULL; + job->rw = READ; + } else { + memset(&job->source, 0, sizeof job->source); + job->source.count = job->dests[0].count; + job->pages = &zero_page_list; + job->rw = WRITE; + } job->fn = fn; job->context = context; @@ -617,6 +630,14 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, } EXPORT_SYMBOL(dm_kcopyd_copy); +int dm_kcopyd_zero(struct dm_kcopyd_client *kc, + unsigned num_dests, struct dm_io_region *dests, + unsigned flags, dm_kcopyd_notify_fn fn, void *context) +{ + return dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context); +} +EXPORT_SYMBOL(dm_kcopyd_zero); + void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc, dm_kcopyd_notify_fn fn, void *context) { diff --git a/trunk/include/linux/dm-kcopyd.h b/trunk/include/linux/dm-kcopyd.h index 5e54458e920f..47d9d376e4e7 100644 --- a/trunk/include/linux/dm-kcopyd.h +++ b/trunk/include/linux/dm-kcopyd.h @@ -57,5 +57,9 @@ void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc, dm_kcopyd_notify_fn fn, void *context); void dm_kcopyd_do_callback(void *job, int read_err, unsigned long write_err); +int dm_kcopyd_zero(struct dm_kcopyd_client *kc, + unsigned num_dests, struct dm_io_region *dests, + unsigned flags, dm_kcopyd_notify_fn fn, void *context); + #endif /* __KERNEL__ */ #endif /* _LINUX_DM_KCOPYD_H */