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
在Raid1的寫流程中,bitmap的設置操做主要在bitmap_statrwrite()、bitmap_unplug()、bitmap_endwrite()。blog
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/