#include <linux/types.h>
#include <linux/atomic.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/device-mapper.h>
#include <linux/dm-kcopyd.h>
#include "dm-core.h"
#define SPLIT_COUNT …
#define MIN_JOBS …
#define DEFAULT_SUB_JOB_SIZE_KB …
#define MAX_SUB_JOB_SIZE_KB …
static unsigned int kcopyd_subjob_size_kb = …;
module_param(kcopyd_subjob_size_kb, uint, 0644);
MODULE_PARM_DESC(…) …;
static unsigned int dm_get_kcopyd_subjob_size(void)
{ … }
struct dm_kcopyd_client { … };
static struct page_list zero_page_list;
static DEFINE_SPINLOCK(throttle_spinlock);
#define ACCOUNT_INTERVAL_SHIFT …
#define SLEEP_USEC …
#define MAX_SLEEPS …
static void io_job_start(struct dm_kcopyd_throttle *t)
{ … }
static void io_job_finish(struct dm_kcopyd_throttle *t)
{ … }
static void wake(struct dm_kcopyd_client *kc)
{ … }
static struct page_list *alloc_pl(gfp_t gfp)
{ … }
static void free_pl(struct page_list *pl)
{ … }
static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
{ … }
static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
unsigned int nr, struct page_list **pages)
{ … }
static void drop_pages(struct page_list *pl)
{ … }
static int client_reserve_pages(struct dm_kcopyd_client *kc, unsigned int nr_pages)
{ … }
static void client_free_pages(struct dm_kcopyd_client *kc)
{ … }
struct kcopyd_job { … };
static struct kmem_cache *_job_cache;
int __init dm_kcopyd_init(void)
{ … }
void dm_kcopyd_exit(void)
{ … }
static struct kcopyd_job *pop_io_job(struct list_head *jobs,
struct dm_kcopyd_client *kc)
{ … }
static struct kcopyd_job *pop(struct list_head *jobs,
struct dm_kcopyd_client *kc)
{ … }
static void push(struct list_head *jobs, struct kcopyd_job *job)
{ … }
static void push_head(struct list_head *jobs, struct kcopyd_job *job)
{ … }
static int run_complete_job(struct kcopyd_job *job)
{ … }
static void complete_io(unsigned long error, void *context)
{ … }
static int run_io_job(struct kcopyd_job *job)
{ … }
static int run_pages_job(struct kcopyd_job *job)
{ … }
static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
int (*fn)(struct kcopyd_job *))
{ … }
static void do_work(struct work_struct *work)
{ … }
static void dispatch_job(struct kcopyd_job *job)
{ … }
static void segment_complete(int read_err, unsigned long write_err,
void *context)
{ … }
static void split_job(struct kcopyd_job *master_job)
{ … }
void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
unsigned int num_dests, struct dm_io_region *dests,
unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
{ … }
EXPORT_SYMBOL(…);
void dm_kcopyd_zero(struct dm_kcopyd_client *kc,
unsigned int num_dests, struct dm_io_region *dests,
unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
{ … }
EXPORT_SYMBOL(…);
void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
dm_kcopyd_notify_fn fn, void *context)
{ … }
EXPORT_SYMBOL(…);
void dm_kcopyd_do_callback(void *j, int read_err, unsigned long write_err)
{ … }
EXPORT_SYMBOL(…);
#if 0
int kcopyd_cancel(struct kcopyd_job *job, int block)
{
return -1;
}
#endif
struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *throttle)
{ … }
EXPORT_SYMBOL(…);
void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
{ … }
EXPORT_SYMBOL(…);
void dm_kcopyd_client_flush(struct dm_kcopyd_client *kc)
{ … }
EXPORT_SYMBOL(…);