3. 移植您的檔案系統

3.1. 為什麼要轉換?

將檔案系統轉換為 iomap 有幾個原因。

  1. 經典的 Linux I/O 路徑效率不高。 Pagecache 操作一次鎖定一個基本頁面,然後呼叫檔案系統以僅返回該頁面的對映。 直接 I/O 操作一次構建一個檔案塊的 I/O 請求。 這對於像 ext2 這樣的直接/間接對映的檔案系統來說已經足夠好,但對於像 XFS 這樣的基於範圍的檔案系統來說效率非常低。

  2. 僅透過 iomap 支援大型頁(folios);沒有計劃轉換舊的 buffer_head 路徑以使用它們。

  3. 只有透過 iomap 才支援直接訪問類記憶體裝置上的儲存 (fsdax)。

  4. 降低了各個檔案系統維護人員的維護開銷。 iomap 本身處理常見的 pagecache 相關操作,例如分配、例項化、鎖定和解鎖頁(folios)。 使用 iomap 的檔案系統不需要實現 ->write_begin()、->write_end() 或 direct_IO address_space_operations。

3.2. 如何轉換檔案系統?

首先,從您的原始碼中新增 #include <linux/iomap.h>,並將 select FS_IOMAP 新增到您的檔案系統的 Kconfig 選項中。 構建核心,使用 -g all 選項在檔案系統支援的各種配置上執行 fstests,以構建哪些測試透過和哪些測試失敗的基線。

推薦的方法是首先實現 ->iomap_begin(如果需要,還有 ->iomap_end),以允許 iomap 獲取檔案範圍的只讀對映。 在大多數情況下,這是對現有 get_block() 函式的相對簡單的轉換,用於只讀對映。 FS_IOC_FIEMAP 是一個很好的首選目標,因為它很容易實現對其的支援,然後從使用者空間確定範圍對映迭代是否正確。 如果 FIEMAP 返回正確的資訊,則這是一個很好的跡象,表明其他只讀對映操作也會做正確的事情。

接下來,修改檔案系統的 get_block(create = false) 實現,以使用新的 ->iomap_begin 實現來對映選定讀取操作的檔案空間。 在除錯旋鈕後面隱藏啟用 iomap 對映功能的能力,以用於選定的呼叫路徑。 有必要編寫一些程式碼,以便從 iomap 結構中填充基於 bufferhead 的對映資訊,但可以在不需要實現任何 iomap API 的情況下測試新功能。

一旦只讀功能像這樣工作,就逐個轉換每個高階檔案操作以使用 iomap 原生 API,而不是透過 get_block()。 一次完成一個,迴歸應該是不言而喻的。 您確實有 fstests 的迴歸測試基線,對吧? 建議在處理 I/O 路徑之前,轉換交換檔案啟用、SEEK_DATASEEK_HOLE。 此時的一個可能的複雜性將是由於 bufferheads 轉換緩衝的讀取 I/O 路徑。 然而,緩衝的讀取 I/O 路徑還不需要轉換,但直接 I/O 讀取路徑應該在此階段進行轉換。

此時,您應該檢查您的 ->iomap_begin 函式。 如果它基於 flags 引數的分發在大量程式碼塊之間切換,您應該考慮將其分解為每個操作的 iomap 操作,使用更小、更具內聚性的函式。 XFS 是一個很好的例子。

接下來要做的是在 ->iomap_begin/->iomap_end 方法中實現 get_blocks(create == true) 功能。 強烈建議為寫入操作建立單獨的對映功能和 iomap 操作。 然後將直接 I/O 寫入路徑轉換為 iomap,並開始在檔案系統上認真地使用啟用 DIO 的 fsx 執行。 這將清除新的寫入對映實現引入的許多資料完整性邊緣情況錯誤。

現在,轉換任何剩餘的檔案操作以呼叫 iomap 函式。 這將使整個檔案系統使用新的對映功能,並且在此步驟之後,它們應該在很大程度上被除錯並且可以正常工作。

最有可能的是,此時,緩衝的讀取和寫入路徑仍然需要轉換。 對映功能都應該正常工作,因此所有需要做的就是重寫所有與 bufferheads 互動的程式碼,以與 iomap 和頁(folios)互動。 首先將常規檔案 I/O(沒有任何花哨的功能,如 fscrypt、fsverity、壓縮或 data=journaling)轉換為使用 iomap 會更容易。 一些花哨的功能(fscrypt 和壓縮)尚未在 iomap 中實現。 對於將 pagecache 用於符號連結和目錄的非日誌檔案系統,您也可以嘗試將其處理轉換為 iomap。

其餘的留給讀者作為練習,因為它對於每個檔案系統都將是不同的。 如果您遇到問題,請透過電子郵件傳送給 get_maintainers.pl 中的人員和列表尋求幫助。