MD中bitmap源代码分析--设置流程

1. 同步/异步刷磁盘

  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批量下刷。spa

2. 写流程Bitmap的设置

  在Raid1的写流程中,bitmap的设置操做主要在bitmap_statrwrite()、bitmap_unplug()、bitmap_endwrite()。blog

  bitmap_statrwrite(),该函数在raid1中的make_request()中调用。在提交每一个盘的bio到pending_bio_list以前调用该函数。队列

  bitmap_statrwrite()的主要工做:进程

    1. 是对写请求的chunk对应bit置1;
    2. 设置对应bit的bitmap_attr为BITMAP_PAGE_DIRTY;
    3. 用*bmc来作还没有完成的写请求计数。

  具体流程以下图所示:内存

 

  1. 若是是延迟写,则增长延迟写计数;
  2. 因为一个写操做涉及的数据段可能对应多个数据块(bitmap-chunk指定的大小),对于每一个这样的数据块:

    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页:

  1. 若是页属性为BITMAP_PAGE_DIRTY,则将该页写入磁盘,同时清除BITMAP_PAGE_DIRTY。等待写入结束后返回。
  2. 若是页属性为BITMAP_PAGE_NEEDWRITE,则将该页写入磁盘,同时清除BITMAP_PAGE_NEEDWRITE。返回。

  这里须要注意的是,若是只有BITMAP_PAGE_NEEDWRITE标记的页,是不须要等待的,由于bit的清除并非很关键,即便这个信息丢失,最多不过是多余的同步操做而已,没有反作用。而bit的设置,则须要保证写入磁盘的“可靠”后,才能进行盘阵chunk的写入;不然在chunk数据写入磁盘时,对应的bitmap中的bit写入磁盘前,盘阵出现异常,则可能致使数据不一致而bitmap不能发觉。

bitmap_unplug()函数实现了下面两种机制:

  实现bitmap同步刷磁盘

  1. unplug函数的执行在写下发以前进行。raid1守护进程执行flush_pending_writes(),这个流程首先调用bitmap_unplug()处理,调用generic_make_request()下发chunk数据的写请求;
  2. bit写盘彻底结束以后,才退出unplug函数。页属性BITMAP_PAGE_DIRTY 时,bitmap_unplug()是等待write_page()写盘完成以后才退出的。实现了bitmap同步刷磁盘,确保了数据的可靠性。

  实现bitmap批量刷磁盘

  1. bitmap_startwrite和bitmap_unplug两步实现。bitmap_unplug要遍历全部bitmap file缓存的page,bitmap_startwrite只针对一次写操做对应的bitmap file缓存的page。

 

  bitmap_endwrite()写完成后,取出对应数据段的bitmap内存结构:

  1. COUNT递减;
  2. 若是COUNT<=2,则设置对应filemap页的BITMAP_PAGE_CLEAN属性;
  3. 若是有chunk写失败,则设置对应bitmap的*bmc的NEEDED标志。表示须要同步。

  具体的函数代码流程以下图所示:

3. 同步流程Bitmap的设置

  bitmap_start_sync()。在chunk同步操做开始时,调用该函数。这个函数获取bitmap的内存结构:

  1. 若是NEEDED标志或者RESYNC标志被设置,就认为该数据块须要同步;
  2. 此时若是盘阵工做无缺,则清除NEEDED标志,设置RESYNC标志;
  3. 若是NEEDED和RESYNC都没有设置,则认为该数据块不须要同步。

  bitmap_end_sync()。chunk同步完成后,调用该函数。这个函数获取bitmap的内存结构:

  1. 若是RESYNC标志被设置,则清除该标志;
  2. 若是同步是失败的,则设置NEED位;
  3. 若是同步成功,而且COUNT<=2,则设置该页属性为BITMAP_PAGE_CLEAN,表示该页存在须要清除的bit位。

 

转载请注明出处:http://www.cnblogs.com/fangpei/

相关文章
相关标签/搜索