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;
|
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 */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче