Q:塊設備層保序功能的作用?
A:通用塊層可以提交一個帶保序標簽(BIO_RW_BARRIER)的BIO到IO請求隊列,塊設備層可以保證在保序BIO之前提交的BIO都先于BIO執行且抵達存儲介質;保序BIO執行完畢后,它需要寫入的數據必定已經抵達存儲介質;在保序IO之后提交的BIO都晚于保序BIO執行,確保BIO不饑餓.
Q:塊設備層保序功能的應用?
A:保序功能最典型的應用場景是文件系統的日志,日志文件系統做文件操作時的日志操作可以簡化為:1.開始事務->2.將修改的元數據寫入到日志空間->3.向日志空間寫入事務提交塊->4.事務結束,這個過程中,IO調度器可能重排2,3步的BIO,導致第3步先于第2步執行完畢,掉電后一個不完整的事務被恢復,文件系統數據被破壞.
Q:塊設備保序功能的實現?
A:BIO從提交到抵達存儲介質需要經過的IO路徑有:IO調度器緩存隊列->IO分發隊列->驅動緩存隊列->磁盤緩存->磁盤介質,保序的真正實現需要借助磁盤提供支持,2.6.27的保序實現會根據磁盤提供的功能做不同的操作.其原理是在收到保序請求后,清空IO調度器中緩存的request,同時在保序請求前后插入刷硬盤緩存指令的request,確保保序請求執行完畢后它和它以前請求寫入的數據都已抵達存儲介質,具體步驟如下:
1.當塊設備層收到保序BIO時,獨立創建一個帶REQ_HARDBARRIER標志的request,調用add_request()向request_queue添加request,插入的位置是ELEVATOR_INSERT_BACK.
2.elv_insert()收到ELEVATOR_INSERT_BACK位置的請求后,將IO調度器中緩沖的request都轉移到分發隊列,同時將保序request插入到分發隊列的最后.
3.底層驅動提供的q->request_fn()函數被調用,elv_next_request()->blk_do_ordered()處理到保序request時,如果q->ordseq=0且硬盤支持沖刷緩存指令,調用start_ordered()開始保序流程.