标签:
Bitmap文件写磁盘分同步和异步两种:
1) 同步置位:当盘阵有写请求时,对应的bitmap文件相应bit被置位,bitmap内存页被设置了DIRTY标志。而在下发写请求给磁盘之前,必须保证bitmap文件下刷完成后才向磁盘发送写请求。这种情况需要等待写bitmap磁盘文件完成,因此是同步的。(由bitmap_unplug()完成)
之所以写bit要在写chunk数据之前就同步刷磁盘,因为如果写请求先下发了,而写bit在这之后刷磁盘的话,当写磁盘过程中发生故障,比如掉电,此时数据是不一致的,而磁盘的bitmap文件中由于还没来得及记录写bit在内存中置位的结果,导致之后会错误的认为数据是一致的。在通过bitmap_statrwrite()和bitmap_unplug()两步实现了bitmap中的bit批量下刷的情况下,实现了同步置位,是为了保证正确性。
2) 异步清零:当下发磁盘的写请求完成后,需要将bitmap内存页中相应的bit清零,然后把bitmap文件下刷。而这个过程不需要等待写bitmap磁盘文件完成,因此是异步的。(由bitmap_daemon_work()完成)
而清bit可以在写请求完成之后异步来做,因为就算是写失败,也不会影响正确性,只是会带来一次额外的同步。异步清零的机制好处在于,在还未清零或者内存位图清0但没有刷到磁盘的时候,又有对该页的写请求到来,就只用增加bmc计数器或者只是把内存位图置位,而不用再写到外存的位图文件中,从而减少了一次写外存位图的io。另外,异步清零也实现了bitmap中的bit批量下刷。
在Raid1的写流程中,bitmap的设置操作主要在bitmap_statrwrite()、bitmap_unplug()、bitmap_endwrite()。
bitmap_statrwrite(),该函数在raid1中的make_request()中调用。在提交每个盘的bio到pending_bio_list之前调用该函数。
bitmap_statrwrite()的主要工作:
具体流程如下图所示:
a) 获取该数据块的bitmap内存结构,即bp数组指向的内容;
b) 如果该数据块对应的counter达到最大值,说明盘阵上该数据区进行的写访问已经太多,盘阵等待太久,此时需要启动设备的队列处理;
c) 如果该数据块上没有正在进行的写操作(*bmc为0),设置filemap对应的bit,设置该bitmap页对应的bitmap_attr属性为BITMAP_PAGE_DIRTY,计数该页上有多少脏的chunk,将该数据块对应的计数*bmc直接设置为2;
d) 如果该数据块的内存位图已经置位,则将*bmc直接是设置为2;
e) 对应的bmc计数累加。
bitmap_unplug()的主要工作,遍历bitmap的所有filemap页:
这里需要注意的是,如果只有BITMAP_PAGE_NEEDWRITE标记的页,是不需要等待的,因为bit的清除并不是很关键,即使这个信息丢失,最多不过是多余的同步操作而已,没有副作用。而bit的设置,则需要保证写入磁盘的“可靠”后,才能进行盘阵chunk的写入;否则在chunk数据写入磁盘时,对应的bitmap中的bit写入磁盘前,盘阵出现异常,则可能导致数据不一致而bitmap不能发觉。
bitmap_unplug()函数实现了下面两种机制:
实现bitmap同步刷磁盘:
实现bitmap批量刷磁盘:
bitmap_endwrite(),写完成后,取出对应数据段的bitmap内存结构:
具体的函数代码流程如下图所示:
bitmap_start_sync()。在chunk同步操作开始时,调用该函数。这个函数获取bitmap的内存结构:
bitmap_end_sync()。chunk同步完成后,调用该函数。这个函数获取bitmap的内存结构:
转载请注明出处:http://www.cnblogs.com/fangpei/
标签:
原文地址:http://www.cnblogs.com/fangpei/p/4656003.html