Chinaunix首页 | 论坛 | 博客
  • 博客访问: 122236
  • 博文数量: 25
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 251
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-29 14:18
个人简介

不以物喜,勿以己悲;乐观向上,持之以恒。

文章分类

全部博文(25)

文章存档

2015年(25)

我的朋友

分类: LINUX

2015-07-19 22:32:14


MD从linux kernel3.1内核开始引入了badblock机制, 该机制在磁盘出现局部坏块时,不会将磁盘剔除,而是进入MD的badblock机制,将这些坏块标识起来,如果能依赖其他磁盘将数据恢复则在数据恢复后,将应用请求返回,否则告知应用raid的坏块数据,此后系统不能再使用这些坏块数据。

这里如果配合remap机制,将坏块重映射到新的位置,坏块就能够得到恢复了。目前软raid中并没有实现remap功能。

以下调研工作基于centos6.3的内核linux-2.6.32-279。


调研
badblock机制有如下问题需要解决:

1. 如何保存badblock信息?
2. 
什么时候会记录badblock信息?
3. 
什么时候会清除badblock信息?
4. 
Badblock机制是否支持数据重映射功能?
5. 
在有Badblock机制保证下何时会踢盘?
6. 
发生badblock后,除了记录badblock信息,raid还会做什么处理?

结构设计


Raid中,每个磁盘中都记录有raid的元数据信息,在centos6.3中,为了支持badblock机制,结构上做了如下调整:
1.修改描述磁盘元数据结构sb_page,增加与badblock机制有关的信息:
    
__u8 bblog_shift:决定raid是否支持badblock机制的开关;
    
__le16 bblog_size:记录badblock信息占用的数据大小(以512B为单位);
    
__le32 bblog_offset:记录badblock元数据的信息在磁盘上的起始位置。
2. 
新加描述badblock的元数据结构bb_page;
3. 
在描述磁盘信息的结构中增加结构badblock,其包含信息如下:
    
int count:坏块个数;
    
int unacked_exist:描述是否有未被处理的坏块;
    
int shift:用来表示坏块数据的单位。如果为0则为1个sector(512B);如果为1则为1K;如果为2则为2K,以此类推;为-1,表示关闭badblock的支持;
    
u64 *page:记录坏块位置以及长度等信息,为4K大小,每个坏块信息长度占8B,所以最大能够记录512个坏块信息;
    
sector_t sector:记录sb_page中的bblog_offset信息;
    
sector_t size:记录sb_page中的bblog_size信息。

badblock实现


除了元数据读写发生错误依然会踢盘外,在badblock机制保障下,正常IO路径一旦发生了读写错误,会调用函数md_set_badblocks,将当前数据位置offset(单位sector)以及数据长度size(单位sector)标记在badblock list中。

Badblock list的特性与实现方式如下:
1. Badblock机制中申请了一个page(4K)的空间来存储badblocks,每64位存储一个badblock信息,共可以存储512badblock信息,超过512badblocks,将没有空间存储而导致踢盘操作<踢盘触发点>
2. 
64位存储的badblock信息内容为:
    
9位表示该badblock的区域长度,所以最长可表示512<最大的坏块区域长度>
    
1位暂未使用
    
中间的54位长度表示badblock的起始扇区
3. 
一个page可以保存512badblock,这些badblock按照起始扇区从小到大排序
4.
 Badblock区域如果相邻可以合并,但是合并后的区域长度最大为512sectors
5. 
为了保证badblock的顺序,增加/清除一条badblock信息时,先按照二分查找法,找到插入位置,然后直接使用内存拷贝函数memmove进行位置的调整;
6. 
判断某个数据块是否有错误,也是通过以上的二分查找法,如果确认数据块在badblock list中有记录,则认为此数据块已经为bad
7. 
Raid的主控线程在检查到某个数据块为bad时,会触发局部rebuild操作,直到该块被修复。当一个bad的块能够被再次写入数据时,则认为该块修复完成可以清除其在badblock list中的记录,清除时会涉及到一条badblock信息是否进行拆分的处理。

读写错误处理


当正常读写发生错误时,会首先尝试设置该块为bad
1. 如果发现badblock机制没有开启或者当前磁盘已经有512badblocks,则设置该块为bad失败,触发踢盘操作;
2. 
如果badblock机制开启且当前磁盘badblocks个数没有达到512个,则设置bad成功,然后尝试局部数据rebuild操作,直到所有的badblock块都被修复为止<此部分会影响正常IO性能>


raid5为例,当同一个条带中有两个磁盘及以上发生了读写错误,此时数据校验失败,就会给上层应用返回错误,导致上层应用终止;但是如果一个条带只有一个磁盘上发生了错误,会通过校验可以获取到正确的数据,此时上层应用正常运行。

Mdadm工具调研


经过调研发现,centos6.3平台自带的mdadm-3.2.3-9工具默认并不支持badblock机制的raid创建。调研了高版本mdadm-3.2.5,默认也不支持badblock机制的raid创建。通过给mdadm工具打patch可以支持创建带有badblock机制的raid

模拟测试


测试平台
centos6.3
测试工具dd(测试读/写,粒度4K)
Raid5参数chunk=64kbitmap-chunk=2048kmetadata=1.2
测试方法cbd设备模拟同一位置坏块,在cbdlvm设备上创建raid5
测试用例
1.
 三块磁盘,不开启badblock机制
   
测试结果:raid5在检测到磁盘有错误IO返回时,直接踢盘
2.
 三块磁盘,开启badblock机制
   
测试结果:raid5在检测到磁盘有错误IO返回时,不踢盘,但是当同一条带错误次数>1次,上层IO会终止;
                  
当同一条带只有1个错误时,应用会继续进行,可以看到每个盘上都有数据读写,尝试对坏块做局部修复操作,如果修复不了,就会将该sector标记为bad

测试总结

1. 不开启badblock机制时,如果发生IO错误,立刻踢盘;
2. 
开启badbblock机制时,发生IO错误(错误上限512),不会立刻踢盘。当同一条带超过1次错误,上层应用终止;否则上层应用继续运行,只是会做局部修复,应用读写性能下降。

缺陷与问题


1. 
当某个区域发生读写错误时,只是标识为坏块,并没有实现remap机制,不能将坏块区域的数据remap到磁盘其他位置保存起来。并且主控线程检查到有坏块时,会触发坏块的rebuild操作,进行坏块修复,如果一直修复不成功,此部分会影响IO性能。
2. 
只申请了一个page大小的区域保存坏块信息,每块磁盘最多只支持512个坏块,且代码设定的比较死,不能动态改变。
3. 
Mdadm工具未能支持使用badblock机制的raid设备创建。

优化方式


1. 
修改mdadm工具,使可支持badblock机制的raid设备创建
2. 
当前badblock机制只支持最大512个坏块,且代码设计比较死,此部分可以重新设计,不过牵扯到磁盘layout结构、元数据信息等变化,改动比较大
3. 
设计数据重映射机制,和badblock机制结合起来,可以增加raid设备的稳定性。

总结


针对前面文档中提到的问题,这里总结如下:
1. 如何保存badblock信息
    
metadata1.2版本,每个磁盘开头部分有一片4K大小的区域,badblock信息保存在此。
2.
 什么时候会记录badblock信息?
    
正常IO错误发生时,会记录badblock信息。
3. 
什么时候会清除badblock信息?
    
当标记为badblock的区域可被写成功时,会清除badblock信息。
4. 
Badblock机制是否支持remap功能?
    
不支持。
5. 
在有Badblock机制保证下何时会踢盘?
    
当错误块超过512时,依然会触发踢盘操作。
6. 
发生badblock后,除了记录badblock信息,raid还会做什么处理?
    
触发坏块rebuild操作,此操作会影响io性能。

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

luo1904272015-09-17 16:54:21

你好,很感谢你的这篇博客,最近也在研究md的坏块这一块,请问你测试的时候是怎么模拟坏块的呢?