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:
Родитель
fbdc86f3bd
Коммит
7f06965390
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче