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/

相關文章
相關標籤/搜索