Chinaunix首页 | 论坛 | 博客
  • 博客访问: 509083
  • 博文数量: 80
  • 博客积分: 1475
  • 博客等级: 上尉
  • 技术积分: 1047
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-01 22:58
文章分类

全部博文(80)

文章存档

2012年(3)

2010年(77)

我的朋友

分类: LINUX

2010-05-04 08:43:46

在device mapper中,需要执行某些异步拷贝。例如,在第一次写快照源前,需要将快照源的数据拷贝到COW设备上;又如,在镜像模块进行恢复时,需要将某个设备的数据拷贝到其他镜像设备上。这些异步拷贝都由“内核拷贝进程”进行。

“内核拷贝进程”提供了一些所谓的“客户端”API函数,由要进行异步拷贝的内核模块使用。其中

int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);

void kcopyd_client_destroy(struct kcopyd_client *kc);

分配和释放“kcopyd客户端”结构。而

int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, unsigned int num_dests, struct io_region *dests, unsigned int flags, kcopyd_notify_fn fn, void *context);

用于向“kcopyd内核拷贝进程”提交一个拷贝任务。其中kc为提交拷贝任务的“kcopyd客户端”,from为拷贝源,num_dests和dests为拷贝目标数目以及拷贝目标数组。在拷贝完成之后,作为“客户端”的内核模块通常要执行某些善后工作,这是在参数中指定了回调函数和回调上下文。

每个提交上来的拷贝任务都会被“内核拷贝进程”添加到任务链表中。根据任务所处的阶段不同,有三个这样的链表:i)等待页面的任务链表_pages_jobs;ii)有页面、等待发起I/O的任务_io_jobs;iii)已经完成的任务_complete_jobs。“内核拷贝进程”的主要任务是循环处理这三个任务链表。

任务刚提交时,被加入到_pages_jobs链表,在从“kcopyd客户端”的页面池中分配所需个数的页面后,这个任务会转移到_ios_jobs链表。

任务刚开始加入到_ios_jobs链表时,rw标志为读,一旦调度,将从拷贝源读取数据到任务的页面,然后通过设定的回调函数将rw标志改为写,并重新插入到_ios_jobs链表。再次调度时,会将任务的页面中的数据拷贝到所有的拷贝目标,在完成之后,回调函数把这个任务又转移到_complete_jobs链表。

_complete_job链表中的任务是需要进行善后处理的,包括将使用的页面重新回收到“kcopyd客户端”的页面池中,并将kcopyd任务从链表中取出,并释放,最终调用“客户端”内核模块指定的回调函数,即kcopyd_copy函数的fn参数。

阅读(2684) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~