Commit 7f069653 authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Alasdair G Kergon

dm kcopyd: add dm_kcopyd_zero to zero an area

This patch introduces dm_kcopyd_zero() to make it easy to use
kcopyd to write zeros into the requested areas instead
instead of copying.  It is implemented by passing a NULL
copying source to dm_kcopyd_copy().

The forthcoming thin provisioning target uses this.
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent fbdc86f3
...@@ -66,6 +66,8 @@ struct dm_kcopyd_client { ...@@ -66,6 +66,8 @@ struct dm_kcopyd_client {
struct list_head pages_jobs; struct list_head pages_jobs;
}; };
static struct page_list zero_page_list;
static void wake(struct dm_kcopyd_client *kc) static void wake(struct dm_kcopyd_client *kc)
{ {
queue_work(kc->kcopyd_wq, &kc->kcopyd_work); queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
...@@ -254,6 +256,9 @@ int __init dm_kcopyd_init(void) ...@@ -254,6 +256,9 @@ int __init dm_kcopyd_init(void)
if (!_job_cache) if (!_job_cache)
return -ENOMEM; return -ENOMEM;
zero_page_list.next = &zero_page_list;
zero_page_list.page = ZERO_PAGE(0);
return 0; return 0;
} }
...@@ -322,7 +327,7 @@ static int run_complete_job(struct kcopyd_job *job) ...@@ -322,7 +327,7 @@ static int run_complete_job(struct kcopyd_job *job)
dm_kcopyd_notify_fn fn = job->fn; dm_kcopyd_notify_fn fn = job->fn;
struct dm_kcopyd_client *kc = job->kc; struct dm_kcopyd_client *kc = job->kc;
if (job->pages) if (job->pages && job->pages != &zero_page_list)
kcopyd_put_pages(kc, job->pages); kcopyd_put_pages(kc, job->pages);
/* /*
* If this is the master job, the sub jobs have already * If this is the master job, the sub jobs have already
...@@ -484,6 +489,8 @@ static void dispatch_job(struct kcopyd_job *job) ...@@ -484,6 +489,8 @@ static void dispatch_job(struct kcopyd_job *job)
atomic_inc(&kc->nr_jobs); atomic_inc(&kc->nr_jobs);
if (unlikely(!job->source.count)) if (unlikely(!job->source.count))
push(&kc->complete_jobs, job); push(&kc->complete_jobs, job);
else if (job->pages == &zero_page_list)
push(&kc->io_jobs, job);
else else
push(&kc->pages_jobs, job); push(&kc->pages_jobs, job);
wake(kc); wake(kc);
...@@ -592,14 +599,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, ...@@ -592,14 +599,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
job->flags = flags; job->flags = flags;
job->read_err = 0; job->read_err = 0;
job->write_err = 0; job->write_err = 0;
job->rw = READ;
job->source = *from;
job->num_dests = num_dests; job->num_dests = num_dests;
memcpy(&job->dests, dests, sizeof(*dests) * num_dests); memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
if (from) {
job->source = *from;
job->pages = NULL; 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->fn = fn;
job->context = context; job->context = context;
...@@ -617,6 +630,14 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, ...@@ -617,6 +630,14 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
} }
EXPORT_SYMBOL(dm_kcopyd_copy); 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, void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
dm_kcopyd_notify_fn fn, void *context) dm_kcopyd_notify_fn fn, void *context)
{ {
......
...@@ -57,5 +57,9 @@ void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc, ...@@ -57,5 +57,9 @@ void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
dm_kcopyd_notify_fn fn, void *context); dm_kcopyd_notify_fn fn, void *context);
void dm_kcopyd_do_callback(void *job, int read_err, unsigned long write_err); 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 /* __KERNEL__ */
#endif /* _LINUX_DM_KCOPYD_H */ #endif /* _LINUX_DM_KCOPYD_H */
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