1. 大小寫摺疊¶
bcachefs 支援使用常規的 chattr +F (S_CASEFOLD, FS_CASEFOLD_FL) 大小寫摺疊屬性進行大小寫不敏感的檔案和目錄查詢。
大小寫摺疊的主要用例是與其他檔案系統(例如 NTFS 和 Wine/Proton)編寫的軟體的相容性,這些軟體依賴於大小寫摺疊的查詢。利用檔案系統級別的大小寫摺疊可以大大提高許多應用程式和遊戲的載入時間。
大小寫摺疊支援需要啟用 CONFIG_UNICODE 的核心。一旦目錄被標記為大小寫摺疊,超級塊上就會啟用一個功能位,該功能位將檔案系統標記為使用大小寫摺疊。當啟用大小寫摺疊的功能位時,如果沒有啟用 CONFIG_UNICODE,則無法在該核心上掛載該檔案系統。
在查詢/查詢方面:大小寫摺疊是透過使用 utf8_casefold 函式分配一個 BCH_NAME_MAX 長度的新字串來摺疊查詢字串來實現的。
在目錄項方面:大小寫摺疊是透過確保 bkey 的雜湊值由大小寫摺疊的字串生成,並將快取的大小寫摺疊名稱與目錄項中的常規名稱一起儲存來實現的。
結構看起來像這樣
常規:[目錄項資料][常規名稱][空][空]...
大小寫摺疊:[目錄項資料][reg 長度][cf 長度][常規名稱][大小寫摺疊名稱][空][空]...
(請注意,此處的 NUL 的數量僅用於說明;它們的計數可能因鍵而異,如果鍵與 sizeof(u64) 對齊,它們甚至可能不存在。)
這是高效的,因為它意味著對於所有需要大小寫摺疊的檔案查詢,它具有與常規查詢相同的效能:雜湊比較和名稱的 memcmp。
1.1. 原理¶
此係統考慮了幾種設計:一種是引入 dirent_v2,但這會很痛苦,特別是當雜湊系統僅支援單一鍵型別時。這也需要 BCH_NAME_MAX 在版本之間更改,以及一個新的功能位。
另一種選擇是不儲存兩個長度,而只是取常規名稱的長度和連續/2的大小寫摺疊名稱的長度作為長度。這將假設常規長度 == 大小寫摺疊長度,但這可能不是真的,如果大寫 Unicode 字形具有與小寫 Unicode 字形不同的 UTF-8 編碼。在這種情況下可能會忽略大小寫摺疊快取,但決定簡單地將兩個字串長度編碼在鍵中,以避免如果遇到此極端情況時出現隨機效能問題。
最終確定的選項是使用 d_type 中的一個空閒位將目錄項標記為具有大小寫摺疊快取,然後將名稱塊的前 4 個位元組視為長度。您可以在 bch_dirent 中的聯合的 d_cf_name_block 成員中看到這一點。
使用功能位是為了允許大多數使用者啟用大小寫摺疊支援,但也允許一些不需要該功能的使用者仍然可以使用 bcachefs,因為 CONFIG_UNICODE 會因為使用的表而顯著增加核心大小,這可能是決定是否使用 bcachefs(例如,對於嵌入式平臺)的因素。
其他檔案系統(如 ext4 和 f2fs)具有用於大小寫摺疊編碼的超級塊級別選項,但 bcachefs 目前不提供此選項。 ext4 和 f2fs 不公開任何編碼,除了單一的 UTF-8 版本。當需要未來的編碼時,可以使用 opts 機制輕鬆新增它們。
1.2. dentry/dcache 注意事項¶
目前,在大小寫摺疊目錄中,bcachefs(與其他檔案系統一樣)不會快取負 dentry。
這是因為目前這樣做會在以下情況下出現問題
在大小寫摺疊目錄中查詢檔案“blAH”
在大小寫摺疊目錄中建立檔案“BLAH”
在大小寫摺疊目錄中查詢檔案“blAH”
如果快取了負 dentry,這將失敗。
這有點次優,但將來可以透過一些 vfs 工作來修復。
1.3. 參考¶
(來自 Peter Anvin,在郵件列表中)
值得注意的是,Microsoft 基本上已宣告他們的“推薦”大小寫摺疊(大寫)表將永久凍結(對於在格式化時建立磁碟上轉換表的情況下,用於新的檔案系統例項)。據我所知,他們從未支援 BMP 程式碼點的 1:1 轉換以外的任何內容,也沒有規範化。
exFAT 規範枚舉了完整的推薦大寫表,儘管格式有點煩人(基本上是壓縮資料的十六進位制轉儲)
https://learn.microsoft.com/en-us/windows/win32/fileio/exfat-specification