F2FS

**F2FS**（英語：**Flash-Friendly File System**）是一種快閃記憶體檔案系統，主要由金載極（韓語：김재극）在三星集團研發，適合 Linux 核心使用。

此檔案系統起初是為了 NAND 快閃記憶體的儲存裝置設計（諸如固態硬碟、eMMC 和 SD 卡），這些裝置廣泛存在於自行動裝置至伺服器領域。

三星應用了日誌結構檔案系統的概念，使它更適合用於儲存裝置。

## 特性

* 多頭紀錄檔（Multi-head logging）
* 對目錄項的多層雜湊表
* 靜態 / 動態冷熱資料分離
* 自適應記錄方案
* 可組態操作單元
* 雙檢查點
* 回滾和前滾恢復
* Heap-style 塊分配
* TRIM/FITRIM 支援
* 連線的檔案系統 / 檔案碎片整理
* 行內 xattrs / 資料 / 目錄
* 離線檔案系統檢查（檢查和修復不一致）)
* 線性一致性
* 檔案系統級加密
* 離線調整大小
* 內部定期資料重新整理
* 範圍快取

## 設計

### 磁碟上布局

F2FS 將整個卷分成多個段（segment），每個段固定為 2 MB。一個節（section）由連續的段組成，一個區（zone）由一組節組成。預設情況下，節與區被設定為相同的大小，但使用者可以用 `mkfs` 輕鬆修改大小。

F2FS 將整個卷劃分為六個區域，除了超級塊（superblock）以外的所有區都由多個段組成，如下所述。

**超級塊（Superblock，SB）**
: 超級塊位於分割區起始處，共有兩個副本以避免檔案系統損壞。它包含基本的分割區資訊和一些預設的 F2FS 參數。

**檢查點（Checkpoint，CP）**
: 檢查點包含檔案系統資訊，有效 NAT/SIT 集的點陣圖，孤立 inode 列表，以及當前活動段的摘要條目。

**段資訊表（SIT）**
: 段資訊表包含主區域塊的有效塊數量和有效點陣圖。

**節點位址表（NAT）**
: 節點資訊表主區域節點塊的位址表。

**段摘要區（SSA）**
: 段摘要區包含的條目包含主區域資料和節點塊的所有者資訊。

**主區域（Main Area）**
: 主區域包含檔案和目錄資料及其索引（indices）。

為了避免檔案系統與快閃記憶體之間的對齊錯誤，F2FS 將 CP 的起始塊位址與段大小對齊。它還通過在 SSA 區域中預留一些段來將「主區」起始塊位址與區的大小對齊。

### 元資料結構

F2FS 使用檢查點方案來維護檔案系統的完整性。在掛載時，F2FS 首先嘗試掃描 CP 區域來尋找最後的有效檢查點資料。為了縮短掃描時間，F2FS 只使用 CP 的兩個副本。其中一個總是指示最後的有效資料，這被稱為影子副本機制。除了 CP 之外，NAT 和 SIT 也使用影子副本機制。為了保證檔案系統的一致性，每個 CP 指向的 NAT 和 SIT 副本都是有效的。

### 索引結構

關鍵的資料結構是「節點」。與傳統的檔案結構類似，F2FS 有三種類型的節點：inode，直接節點，間接節點。F2FS 將 4 KB 分配給一個 inode 塊，其中包含 923 個資料塊索引（data block indices），兩個直接節點指標，兩個間接節點指標，以及一個 double 間接節點指標，如下所述。一個直接節點塊包含 1018 個資料塊索引，而間接節點塊包含 1018 個節點塊索引。因此，一個 inode 塊（即一個檔案）涵蓋：

```
4 KB × (923 + 2×1018 + 2×10182 + 10183) = 3.94 TB
```

注意，所有節點塊都經 NAT 對映，因此每個節點的位置都經 NAT 轉換。為了緩解漫遊樹問題，F2FS 能夠切斷葉資料寫入引起的節點更新傳播。

### 目錄結構

一個目錄條目（dentry）占用 11 個位元組，由以下屬性組成。

一個目錄條目塊由及檔名組成。有一個點陣圖用於記錄每個目錄條目是否有效。一個目錄條目塊占用 4 KB，結構如下：

```
目录条目块 (4 K) = 位图 (27 字节) + 保留 (3 字节) +
                      目录项 (11 * 214 字节) + 文件名 (8 * 214 字节)
```

F2FS 為目錄結構實現了多級雜湊表，每一級有一個包含專用雜湊桶數的雜湊表，如下所示。「A (2B)」表示桶包含 2 個資料塊。

**項**
: A 表示桶（bucket）

　
: B 表示塊（block）

　
: N 表示目錄雜湊最大深度（MAX\_DIR\_HASH\_DEPTH）

```
level #0    A(2B)
level #1    A(2B) - A(2B)
level #2    A(2B) - A(2B) - A(2B) - A(2B)
    ...
level #N/2  A(2B) - A(2B) - A(2B) - A(2B) - A(2B) - ... - A(2B)
    ...
level #N    A(4B) - A(4B) - A(4B) - A(4B) - A(4B) - ... - A(4B)
```

當 F2FS 在一個目錄中找一個檔名時，首先計算出該檔名的雜湊值，然後 F2FS 掃描級別 #0 的雜湊表一尋找由檔名及其 inode 編號組成的目錄條目。如果未找到，F2FS 繼續尋找級別 #1 的雜湊表。F2FS 通過此方法逐級掃描由 1 至 N 的每層雜湊表。在每一層中，F2FS 只需掃描由以下等式確定的一個桶（bucket），因此展現出 O (log (# of files)) 的複雜度。

```
 级别#n中要扫描的桶（bucket）数 = (散列值) % (级别#n中的桶数)
```

在建立檔案時，F2FS 找到一個能涵蓋檔名的空的連續槽。F2FS 以同樣的方式由 1 至 N 尋找各級雜湊表中的空槽。

### 預設的塊分配

在執行時，F2FS 在「主要區域：」內管理六個活動紀錄檔：熱 / 暖 / 冷節點和熱 / 暖 / 冷資料。

基於紀錄檔的檔案系統（LFS）有兩種空閒空間管理方案：穿插記錄（threaded log）與複製並壓縮（copy-and-compaction）。後者也稱為清理（cleaning），很適合有良好順序寫入效能的裝置，因為空閒空間總用於寫入新資料。但它會在發生高利用率時遭遇「清理」的開銷。穿插記錄則受到隨機寫入效能的影響，但沒有「清理」過程。F2FS 採用混合方案，預設採用「複製並壓縮」，但根據檔案系統的狀態將策略動態變更為「穿插記錄」方案。

為使 F2FS 與基於快閃記憶體的儲存保持一致，F2FS 以一個節（section）為單位分配一個段（segment）。F2FS 預期節的大小與 FTL 中的垃圾收集單元大小相同。為考慮 FTL 中的對映粒度，F2FS 將活動紀錄檔的每個節分配給儘可能多的不同區域。 FTL 可以根據其對映粒度將活動紀錄檔資料寫入一個單位配置。

### 清理流程

F2FS 在需要時和後台閒置時進行清理。按需清理在沒有足夠的空閒分段（segments）服務 VFS 呼叫時觸發。後台清理器由一個核心執行緒執行，在系統空閒時觸發清理作業。

F2FS 支援兩種受者選擇策略：貪婪、成本效益演算法。在貪婪演算法中，F2FS 選擇有最小有效塊數的受者段。在成本效益演算法中，F2FS 根據段的年齡和有效塊數量選擇受者段，以解決貪婪演算法中存在的紀錄檔塊抖動問題。F2FS 使用貪婪演算法進行按需清理，後台清理器則使用成本效益演算法。

為辨識受者段中的資料是否有效，F2FS 管理了一個點陣圖，其中用一個位元表示一個塊的有效性，覆蓋主區域所有塊的位元流組成了該點陣圖。

## 相關條目

* 檔案系統的對比
* 檔案系統列表

## 參考資料

## 外部連結

* F2FS 文件於 kernel.org（頁面存檔備份，存於網際網路檔案館）（英文）