分类: 服务器与存储
2010-05-04 08:35:16
在Linux软RAID实现中,将多路径也作为一种特性进行支持。使用mdadm基于软RAID构造多路径的命令行格式相似。唯一的区别在于,在创建其它级别的RAID设备时,每个sd设备号都是代表不同的物理磁盘;但是在使用mdadm基于软件RAID创建multiple设备时,使用到的sd设备号都是指向相同的公用磁盘驱动器。Mdadm并不检查这两条路径是否指向同一个磁盘(LUN),因此在设置之初需要确保这一点。创建multipath的示例如下:
mdadm --create /dev/md1 --level=multipath --raid-devices=2 /dev/sdb /dev/sdc
这里,/dev/sdb和/dev/sdc是通过HBA驱动程序向上层呈现的对存储设备的同一个磁盘的逻辑块设备名。上述命令会将/dev/sdb和/dev/sdc这两个不同路径对应的成员磁盘“绑定”成为一个软RAID设备/dev/md1,而对该设备的访问相当于通过不同的物理链路访问同一个磁盘。
除了通用的表示RAID设备的内核结构mddev_t和标识成员磁盘的内核结构mdk_rdev_t之外,mulitpath设备有两个重要的数据结构。其中multipath_conf_t是表示multipath设备的的私有数据结构,定义如下:
struct multipath_info {
mdk_rdev_t *rdev; //指向组成multiple device的第一个成员磁盘的内核结构的指针
};
struct multipath_private_data {
mddev_t *mddev;
struct multipath_info *multipaths;
int raid_disks; //本multiple device的成员磁盘数目
int working_disks; //本multiple device中可工作的成员数目
spinlock_t device_lock;
struct list_head retry_list; //本multiple device的重试链表
mempool_t *pool;
};
typedef struct multipath_private_data multipath_conf_t;
raid_disks给出了组成该设备的成员磁盘的个数,而working_disks给出了其中可工作的成员磁盘的个数。Multipaths指向成员磁盘数组。
而multipath_bh结构代表了在multiple device的某条路径(即该路径对应的成员磁盘)上执行I/O请求的缓冲头结构。
struct multipath_bh {
mddev_t *mddev; //回指向multiple device的指针
struct bio *master_bio; //指向对RAID设备的原始bio
struct bio bio; //在该路径对应的成员磁盘上执行的bio
int path; //该路径对应的成员磁盘在multiple device中的索引
struct list_head retry_list; //加入到multiple device的重试链表中
};
master_bio指向对multiple device的原始bio,path为路径编号,也就是这条路径对应的成员设备在multiple device的组成磁盘中的编号,bio则是该路径(成员磁盘)上执行的bio。
如果上层有针对multiple device的I/O请求,最终将到达multipath_make_request函数。它将为这个请求创建一个multipath_bh,在其中保存原始的请求master_bio,并从multiple device中获得一条路径。如果无法得到路径,则向上层报告错误;否则要构造在这条路径对应的成员磁盘上进行操作的bio,除了更改bio的起始扇区bi_sector和请求设备bi_bdev等域之外,还需要将上面的multipath_bh结构保存在bio的bi_private域中,并设定bi_end_io回调函数为multipath_end_request,之后在这条路径对应的成员磁盘上调度请求。
上面叙述中,bio设置的后面两步主要作用在于这个路径上调度请求完成之后。设置bi_private域的目的是期望找到multipath_bh结构,并通过它找到原始的I/O请求bio以及multiple device的内核结构mddev_t;设置multipath_end_request是在成员磁盘上请求执行完成之后作善后处理:如果执行成功,则通过保存的对multiple device的原始bio向上层报告成功;如果执行失败,且是预读,则向上层报告错误(也就是说,我们不对预读在其它路径上进行重试);如果对其它操作(读或写)执行失败,则需要将这个路径对应的成员磁盘设定为故障,将这个multipath_bh链接到multiple device的重试列表中,然后唤醒multipathd线程。
如果multipathd线程获得调度,会处理multiple device的重试链表中的所有bio。对于每个bio,重新获得一条路径(注意到上次处理过的成员磁盘已经设置为故障,对应的路径将不会再次使用),构造对应成员磁盘的bio请求,并调度之。
在multiple device中获得路径的方法是返回第一个可用的路径,未作读均衡等优化考虑。