MD模块之处理读写过程分析-1
2011-08-03 10:15
525 查看
md可以说是一个虚拟的设备驱动层,它属于块设备驱动,拥有块设备驱动的特点。所以,他实现了块设备操作接口
(对MD的大部分操作均是有md_ioctl接口来实现,少数部分也可由sys文件系统来实现)
按我的理解,我可以把MD模块分为2个部分,一个是控制管理部分,另一个是raid级别实现部分。控制管理部分是一个大的框架,它控制各raid级别模块,他们之间的如何联系的呢?想必看过代码的人都知道了,就是md_k.h中定义的结构体struct mdk_personality,这个结构体中主要定义了一些函数操作集(就像io调度中elevator中定义的一样),这些函数分别由各个raid级别来实现,有些raid级别是不实现某些函数的,这个结构体内容如下:
make_request:块设备处理请求函数。
run:各raid模块启动函数,例如分配内存、建立线程等。
stop:各raid模块停止函数,释放资源。
status:/proc文件系统接口
error_handler:处理读写发生错误的接口
hot_add_disk:在重建过程中,将热备盘加到阵列中。
hot_remove_disk:在重建过程中,移除失效盘接口
spare_active:激活热备盘接口
check_reshape:阵列扩展检查接口
start_reshape:启动扩展接口
这些函数是在raid模块加载时候注册的。
说了这么多还没说到正题呢,呵呵。。。接下来就步入正题。Linxu中md设备是可以通过文件系统访问的,当创建一个MD设备时,用户态的读写请求通过文件系统发送到MD设备中。熟悉linxu内核的人知道,转发请求的函数就是generic_make_request,这个函数最终会调用队列的make_request_fn方法,如果发送到MD设备中,那么这个方法就由md层中的make_request函数来实现(在struct mdk_personality中定义,由各个raid模块来实现)。由于raid算法定义不同,make_request实现的方式也不同。本质上来说,md层的make_request就是把文件系统发送过来的bio根据各raid算法进行重新分发到各个磁盘上。而md层中的make_request函数最终还会调用generic_make_request来下发bio,如果这次下发的对象是具体的物理设备,make_request_fn方法就由系统的__make_request来实现,那么进入io调度层(我会在以后专门一节分析之)。
这里我们以raid5为例,分析make_request是如何转发bio的。其他raid算法这里就不做介绍了。。
static struct block_device_operations md_fops = { .owner = THIS_MODULE, .open = md_open, .release = md_release, .ioctl = md_ioctl, .getgeo = md_getgeo, .media_changed = md_media_changed, .revalidate_disk= md_revalidate, };
(对MD的大部分操作均是有md_ioctl接口来实现,少数部分也可由sys文件系统来实现)
按我的理解,我可以把MD模块分为2个部分,一个是控制管理部分,另一个是raid级别实现部分。控制管理部分是一个大的框架,它控制各raid级别模块,他们之间的如何联系的呢?想必看过代码的人都知道了,就是md_k.h中定义的结构体struct mdk_personality,这个结构体中主要定义了一些函数操作集(就像io调度中elevator中定义的一样),这些函数分别由各个raid级别来实现,有些raid级别是不实现某些函数的,这个结构体内容如下:
struct mdk_personality { char *name; int level; struct list_head list; struct module *owner; int (*make_request)(request_queue_t *q, struct bio *bio); int (*run)(mddev_t *mddev); int (*stop)(mddev_t *mddev); void (*status)(struct seq_file *seq, mddev_t *mddev); /* error_handler must set ->faulty and clear ->in_sync * if appropriate, and should abort recovery if needed */ void (*error_handler)(mddev_t *mddev, mdk_rdev_t *rdev); int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev); int (*hot_remove_disk) (mddev_t *mddev, int number); int (*spare_active) (mddev_t *mddev); sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); int (*resize) (mddev_t *mddev, sector_t sectors); int (*check_reshape) (mddev_t *mddev); int (*start_reshape) (mddev_t *mddev); int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); /* quiesce moves between quiescence states * 0 - fully active * 1 - no new requests allowed * others - reserved */ void (*quiesce) (mddev_t *mddev, int state); };
make_request:块设备处理请求函数。
run:各raid模块启动函数,例如分配内存、建立线程等。
stop:各raid模块停止函数,释放资源。
status:/proc文件系统接口
error_handler:处理读写发生错误的接口
hot_add_disk:在重建过程中,将热备盘加到阵列中。
hot_remove_disk:在重建过程中,移除失效盘接口
spare_active:激活热备盘接口
check_reshape:阵列扩展检查接口
start_reshape:启动扩展接口
这些函数是在raid模块加载时候注册的。
说了这么多还没说到正题呢,呵呵。。。接下来就步入正题。Linxu中md设备是可以通过文件系统访问的,当创建一个MD设备时,用户态的读写请求通过文件系统发送到MD设备中。熟悉linxu内核的人知道,转发请求的函数就是generic_make_request,这个函数最终会调用队列的make_request_fn方法,如果发送到MD设备中,那么这个方法就由md层中的make_request函数来实现(在struct mdk_personality中定义,由各个raid模块来实现)。由于raid算法定义不同,make_request实现的方式也不同。本质上来说,md层的make_request就是把文件系统发送过来的bio根据各raid算法进行重新分发到各个磁盘上。而md层中的make_request函数最终还会调用generic_make_request来下发bio,如果这次下发的对象是具体的物理设备,make_request_fn方法就由系统的__make_request来实现,那么进入io调度层(我会在以后专门一节分析之)。
这里我们以raid5为例,分析make_request是如何转发bio的。其他raid算法这里就不做介绍了。。
相关文章推荐
- MD模块之处理读写过程分析-3
- MD模块之处理读写过程分析-1
- MD模块之处理读写过程分析-1
- MD模块之处理读写过程分析-2
- MD模块之处理读写过程分析-4
- MD模块之处理读写过程分析-2
- MD模块之处理读写过程分析-4
- MD模块之处理读写过程分析-3
- MD模块之处理读写过程分析-4
- MD模块之处理读写过程分析-2
- 记录一则Spark读写和Lost Excutor错误的分析和解决过程 推荐
- C++中读写文件过程中异常处理机制
- Tomcat源码分析(四)------ Request和Response处理的全过程
- struts2请求处理过程源代码分析(1)
- 2410 中断过程处理分析
- vlc学习计划(6)--网络数据流接收处理过程分析
- HDFS追本溯源:租约,读写过程的容错处理及NN的主要数据结构
- Linux内核分析课程5_system_call中断处理过程
- PLUTO平台是由美林数据技术股份有限公司下属西安交大美林数据挖掘研究中心自主研发的一款基于云计算技术架构的数据挖掘产品,产品设计严格遵循国际数据挖掘标准CRISP-DM(跨行业数据挖掘过程标准),具备完备的数据准备、模型构建、模型评估、模型管理、海量数据处理和高纬数据可视化分析能力。
- Linux课程(五):分析system_call中断处理过程