BlobFS 是一個可定址內容的檔案系統,已針對一次寫入、經常讀取的檔案 (例如二進位檔和程式庫) 進行最佳化。在 Fuchsia 上,BlobFS 是所有軟體套件使用的儲存系統。
掛接時,BlobFS 會顯示包含所有檔案 (又稱為 blob) 的單一邏輯目錄:
blob/
├── 00aeb9b5652a4adbf630d04a6ca22668f9c8469746f3f175687b3c0ff6699a49
├── 01289d3e1d2cdbc7d1b4977210877c5bbdffdbad463d992badc149152962a205
├── 018951bcf92091fd5d294cbd1f3a48d6ca59be7759587f28077b2eb754b437c0
└── 01bad8536a7aee498ffd323f53e06232b8a81edd507ac2a95bd0e819c4983138
BlobFS 中的檔案如下:
- 不可變動:blob 建立後,即無法修改 (移除除外)。
- Content-Addressable:系統會從內容中擷取 Blob 名稱。
- 已驗證:系統會使用加密編譯檢查碼確保 blob 資料的完整性。
這些 Blob 屬性讓 BlobfS 成為 Fuchsia 安全性的關鍵元件,以確保軟體套件的內容在執行前可以通過驗證。
BlobFS 的設計和實作
磁碟機格式
BlobFS 會將每個 blob 儲存在非相鄰範圍 (連續的資料區塊範圍) 中連結的清單。每個 blob 都有相關聯的 I 節點,用於說明區塊資料在磁碟上的起始位置,以及 blob 相關中繼資料。
BlobFS 將磁碟 (或其分區) 分成五個區塊:
- Superblock 儲存整個檔案系統的中繼資料,
- Block Map:用來追蹤自由和分配的資料區塊的點陣圖。
- 節點對應:Inodes 的平面陣列 (blob 資料開始在磁碟上的參照位置) 或 ExtentContainers (參照包含部分 blob 資料的數個範圍的參照)。
- Journal,這是確保檔案系統運作的記錄檔,即使裝置在作業期間重新啟動或斷電也一樣;以及
- 「資料區塊」,其中 blob 內容及其驗證中繼資料會以一系列程度儲存。
圖 1:BlobFS 磁碟版面配置
超級封鎖
超級區塊是 BlobFS 格式分區中的第一個區塊。說明檔案系統中其他區塊的位置和大小,以及其他檔案系統層級中繼資料。
掛接 BlobFS 格式的檔案系統時,這個區塊會對應至記憶體並進行剖析,以判斷檔案系統的其餘部分的位置。每當建立新的 blob 時,都會修改區塊,且每當 BlobFS 檔案系統的大小變小或變大時 (適用於 FVM 代管的 BlobFS 執行個體),就會修改區塊。
圖 2:BlobFS 超級區塊
當 BlobFS 由 FVM 管理時,超級區塊會包含一些額外中繼資料,說明包含 BlobFS 檔案系統的 FVM 配量。非 FVM 且大小固定的 BlobFS 圖片會忽略這些欄位 (上圖中的黃色欄位)。
封鎖地圖
區塊地圖是簡易的點陣圖,會將每個資料區塊標示為已分配或未。進行區塊配置時,這張地圖可用來尋找連續範圍 (稱為「擴充」) 的區塊,以將 blob 內容儲存在其中。
圖 3:提供幾種不同大小的區塊地圖範例。
掛接 BlobFS 映像檔時,區塊地圖會對應到記憶體,以供區塊配置器讀取。每當分配區塊 (建立 blob 期間) 或取消配置 (在刪除 blob 期間) 時,區塊對應就會寫回磁碟。
節點對應
節點對應是檔案系統中所有節點的陣列,可能有兩種變化:
- Inodes:描述檔案系統中的單一 blob
- ExtentContainers:指向包含部分 blob 資料的範圍。
這兩種類型的節點都儲存在單一平面陣列中。每個節點都有通用標頭,說明節點的類型以及是否分配節點。這兩種節點類型的大小相同,因此沒有陣列的內部片段化。
節點
檔案系統中的每個 blob 都有對應的 I 節點,用於說明 blob 資料的起始位置,以及一些與 blob 相關的中繼資料。
圖 4:BlobFS Inode 的版面配置。
如為小型 blob,Inode 可能是唯一必要的節點,用來說明 blob 在磁碟中的位置。在本例中,extent_count
為 1,不得使用 next_node
,而 inline_extent
則說明 blob 的單一範圍。
較大的 blob 可能會佔用多個範圍,尤其是在分割的 BlobFS 圖片上。在這個範例中,blob 的第一個範圍會儲存在 inline_extent
中,且所有後續規模都會從 next_node.
開始,儲存在 ExtentContainer 的連結清單中。
圖 5:極端格式 (佔用 64 位元)。Inode 和 ExtentContainer 都使用這種格式。
請注意,此範圍表示法意指一個範圍最多只能有 2**16 個區塊 (超出大小的最大值)。
ExtentContainers
ExtentContainer 會保留數個 (最多 6) 個範圍的參照,用來儲存 blob 的部分內容。
ExtentContainer 中的範圍在邏輯上是連續的 (也就是儲存在 extents[0]
中的 blob 的邏輯可定區塊區塊,然後是 extents[1]
之前),並會依序填入。如果設定了 next_node
,則 ExtentContainer 必須已滿。
圖 6:BlobFS ExtentContainer 的版面配置。
已連結節點清單的屬性
blob 的範圍會儲存在單一 I 節點 (保存第一個範圍) 的連結清單中,以及零或多個 ExtentContainer (每個節點最多可保留 6 個擴充項目)。
這份已連結的清單包含下列資源。違反上述任何屬性會導致 blobf 將 blob 視為毀損。
- 填充在邏輯上皆屬連續:
- 如果節點 A 在清單中節點 B 之前,則節點 A 中所有範圍的邏輯偏移值都低於 blob 內容的邏輯偏移。
- 在指定的 ExtentContainer 中,如果範圍為 x 和 y,假如 x < y,外部 x 對 blob 內容的邏輯偏移就比範圍 y 低。
- 連結新節點之前,系統會封裝節點。換句話說,如果節點有非空值的
next_node
,就必須具有完整的範圍 (*針對 I 節點,以及 ExtentContainers 的 6 範圍)。 - 連結清單中的範圍總數必須與 I 節點的
extent_count
相同。 - 已連結清單中所有範圍的大小總和必須與 Ionic 的
block_count
相同。 - 清單的結尾取決於系統節點中的
extent_count
。不應使用最終節點中的next_node
。
Node 版面配置範例
本節包含一些範例,說明 blob 節點的格式。
範例:單一擴充 blob
圖 7:以單一程度儲存 blob 的節點版面配置
範例:多餘 blob
圖 8:以不同程度儲存的 blob 節點版面配置。請注意,blob 的延伸項目可能會分散到整個磁碟。
Blob 分割
新建立的 BlobFS 映像檔可以產生所有資料區塊。任意大小可以輕易找到,而 blob 通常都是以單一較大的範圍 (或少數很多範圍) 儲存。
隨著時間經過,分配及取消分配 blob 時,區塊地圖會「分割」到許多較小的範圍。新建的 blob 將必須儲存在多個較小的範圍中。
圖 9:片段化區塊地圖。雖然免費區塊可以提供許多,但如果是很廣泛仍可使用。
片段不理想的狀況,原因如下:
- 較慢讀取:讀取片段的 blob 必須在 Node Map 中追蹤指標。這會影響依序讀取和隨機存取讀取
- 較慢的建立與刪除:建立 blob 需要找到免費的擴充功能;如果必須找到許多較小的範圍,則需要較長時間。同樣地,刪除片段化 blob 時,會一併處理並釋放許多擴充功能。
- 中繼資料負擔:如要儲存分段的 blob,就需要更多節點。節點地圖中的節點數量有限,因此可能會耗盡,導致系統無法建立 blob。
目前 BlobFS 並未執行重組作業。
日誌
待辦事項
資料區塊
最後,blob 的實際內容必須儲存在某處。系統會針對此目的指定 BlobFS 映像檔中剩餘的儲存區塊。
每個 blob 的配置程度都足以容納其所有資料,以及一些為 blob 儲存驗證中繼資料而保留的資料區塊。此中繼資料一律儲存在 blob 的第一個區塊。系統會新增中繼資料,讓實際資料一律從區塊對齊的地址開始。
這類驗證中繼資料稱為「Merkle Tree」,這是使用加密編譯雜湊值確保 blob 內容完整性的資料結構。
梅克爾樹
blob 的 Merkle Tree 結構如下 (詳情請參閱 Fuchsia Merkle Roots):
- 每個分葉節點都是單一區塊中資料的 sha256 雜湊。
- 每個非分葉節點都是合併其子項雜湊的 sha256 雜湊。
- 樹狀結構會在有單一 sha256 雜湊的層級終止。
最頂層節點的雜湊值稱為 blob 的「Merkle Root」。 這個值會做為 blob 的名稱。
圖 10:簡化的範例 Merkle Tree。請注意,實際上,每個雜湊值都包含更多資訊 (例如區塊偏移和長度),且每個非分葉節點都會大幅擴大 (特別是每個非分葉節點最多可包含 8192 / 32 == 256 個子項)。
BlobFS 實作
如同其他 Fuchsia 檔案系統,BlobFS 可做為使用者空間程序實作,可透過 FIDL 介面為用戶端提供服務。