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: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
This commit is contained in:
Mikulas Patocka 2011-10-31 20:18:58 +00:00 коммит произвёл Alasdair G Kergon
Родитель fbdc86f3bd
Коммит 7f06965390
2 изменённых файлов: 30 добавлений и 5 удалений

Просмотреть файл

@ -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)
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)
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)
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,
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,
} }
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,
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 */