XFS

**XFS**，一種高效能的紀錄檔檔案系統，最早於 1993 年，由 Silicon Graphics 為他們的 IRIX 作業系統而開發，是 IRIX 5.3 版的預設檔案系統。2000 年 5 月，Silicon Graphics 以 GNU 通用公眾授權條款釋出這套系統的原始碼，之後被移植到 Linux 核心上。XFS 特別擅長處理大檔案，同時提供平滑的資料傳輸。

## 歷史

XFS 的開發始於 1993 年，在 1994 年被首次部署在 IRIX 5.3 上。2000 年 5 月，XFS 在 GNU 通用公眾授權條款下釋出，並被移植到 Linux 上。2001 年 XFS 首次被 Linux 發行版所支援，現在所有的 Linux 發行版上都可以使用 XFS。

XFS 最初被合併到 Linux 2.4 主線中，這使得 XFS 幾乎可以被用在任何一個 Linux 系統上。Arch, Debian, Fedora, openSUSE, Gentoo, Kate OS, Mandriva, Slackware, Ubuntu, VectorLinux 和 Zenwalk 的安裝程式中都可選擇 XFS 作為檔案系統，但由於預設的啟動管理器 GRUB 中存在 bug，以上發行版中只有少數幾個允許使用者在 /boot 掛載點（引導目錄）上使用 XFS 檔案系統。

FreeBSD 在 2005 年 12 月獲得了對 XFS 的唯讀支援，並在次年 6 月引入了試驗性的寫入支援。不過這些只是為了方便使用者從 Linux 上遷移到 FreeBSD 上，並不是為了把 XFS 作為主打檔案系統使用。Red Hat Enterprise Linux 5.4 64 位元版的核心完整支援 XFS，但未包含建立和使用 XFS 的命令列工具（CentOS 正在進行這方面的嘗試），原因是這些軟體套件還不夠穩定。Red Hat Enterprise Linux 7/CentOS 預設使用 XFS 檔案系統。

## 規範

### 容量

XFS 是一個 64 位元檔案系統，最大支援 8exbibytes 減 1 位元組的單個檔案系統，實際部署時取決於宿主作業系統的最大塊限制。對於一個 32 位元 Linux 系統，檔案和檔案系統的大小會被限制在 16tebibytes。

### 檔案系統紀錄檔

紀錄檔檔案系統是一種即使在斷電或者是作業系統崩潰的情況下保證檔案系統一致性的途徑。XFS 對檔案系統元資料提供了紀錄檔支援。當檔案系統更新時，元資料會在實際的磁碟塊被更新之前順序寫入紀錄檔。XFS 的紀錄檔被儲存在磁碟塊的迴圈緩衝區上，不會被正常的檔案系統操作影響。XFS 紀錄檔大小的上限是 64k 個塊和 128MB 中的較大值，下限取決於已存在的檔案系統和目錄的塊的大小。在外置裝置上部署紀錄檔會浪費超過最大紀錄檔大小的空間。XFS 紀錄檔也可以被存在檔案系統的資料區（稱為內建紀錄檔），或者一個額外的裝置上（以減少磁碟操作）。

XFS 的紀錄檔所儲存的是「邏輯」條目，以人類更加容易理解的方式來描述當前正在進行的操作（「物理」紀錄檔與其相反，儲存的是每次操作中被修改的塊）。紀錄檔的更新以非同步的方式進行，避免影響整體效能。

如果發生系統崩潰，可以根據紀錄檔中的記錄來重做並完成崩潰的前一時刻發生的系統操作。崩潰之後首次掛載檔案系統時，會自動進行恢復。恢復的速度不受檔案系統大小的影響，取決於需要重做的系統操作的數量。

對於最近被修改但未完全寫入磁碟的資料，XFS 保證在重新啟動時清零所有未被寫入的資料塊，以防止任何有可能的、由剩餘資料導致的安全隱患（因為雖然從檔案系統介面無法存取這些資料，但不排除裸裝置或裸硬體被直接讀取的可能性）。

### 分配組

XFS 檔案系統內部被分為多個「分配組」，它們是檔案系統中的等長線性儲存區。每個分配組各自管理自己的 inode 和剩餘空間。檔案和資料夾可以跨越分配組。這一機制為 XFS 提供了可伸縮性和並列特性 —— 多個執行緒和行程可以同時在同一個檔案系統上執行 I/O 操作。這種由分配組帶來的內部分割區機制在一個檔案系統跨越多個物理裝置時特別有用，使得最佳化對底層儲存部件的吞吐量利用率成為可能。

### 條帶化分配

在條帶化 RAID 陣列上建立 XFS 檔案系統時，可以指定一個「條帶化資料單元」。這可以保證資料分配、inode 分配、以及內部紀錄檔被對齊到該條帶單元上，以此最大化吞吐量。

### 基於 Extent 的分配方式

XFS 檔案系統中的檔案用到的塊由變長 Extent 管理，每一個 Extent 描述了一個或多個連續的塊。與那些把檔案所有塊都單獨列出來的檔案系統相比，extent 大幅縮短了列表。 
有些檔案系統用一個或多個面向塊的點陣圖管理空間分配 —— 在 XFS 中這種結構被由一對 B + 樹組成的、面向 Extent 的結構替代了；每個檔案系統分配組（AG）包含這樣的一個結構。其中，一個 B + 樹用於索引未被使用的 Extent 的長度，另一個索引這些 Extent 的起始塊。這種雙索引策略使得檔案系統在定位剩餘空間中的 Extent 時十分高效。

### 可變塊尺寸

塊是檔案系統中的最小可單位配置。XFS 允許在建立檔案系統時指定塊的大小，從 512 位元組到 64KB，以適應專門的用途。比如，對於有很多小檔案的應用，較小的塊尺寸可以最大化磁碟利用率；但對於一個主要處理大檔案的系統，較大的塊尺寸能提供更好的效能。...

### 延遲分配

XFS 在檔案分配上使用了惰性計算技術。當一個檔案被寫入快取時，XFS 僅在記憶體中對該檔案保留適當數量的塊，並不立即給資料分配 Extent。實際的塊分配僅在這段資料被沖刷到磁碟時才發生。這一機制提高了將該檔案寫入一組連續塊中的機會，減少碎片的同時提升了效能。

### 稀疏檔案

XFS 對每個檔案提供了一個 64 位元的稀疏位址空間，使得大檔案中的「洞」（空白資料區）不被實際分配到磁碟上。因為檔案系統對每個檔案使用一個 Extent 表，檔案分配表就可以保持一個較小的體積。對於太大以至於無法儲存在 inode 中的分配表，這張表會被移動到 B + 樹中，繼續保持對該目的檔在 64 位元位址空間中任意位置的資料的高效存取。

### 擴充屬性

XFS 通過實現擴充檔案屬性給檔案提供了多個資料流，使檔案可以被附加多個名 / 值對。檔名是一個最大長度為 256 位元組的、以 NULL 字元結尾的可列印字串，其它的關聯值則可包含多達 64KB 的二進位資料。這些資料被進一步分入兩個命名空間中，`root` 和 `user`。儲存在 root 命名空間中的擴充屬性只能被超級使用者修改，user 命名空間中的可以被任何對該檔案擁有寫權限的使用者修改。擴充屬性可以被添加到任意一種 XFS inode 上，包括符號連結、裝置節點、目錄，等等。可以使用 `attr` 這個命令列程式操作這些擴充屬性。`xfsdump` 和 `xfsrestore` 工具在進行備份和恢復時會一同操作擴充屬性，而其它的大多數備份系統則會忽略擴充屬性。

### Direct I/O

對於需要高吞吐量的應用，XFS 實現了直接的 I/O，允許未快取的 I/O 操作直接應用到使用者空間。資料在應用程式的緩衝區和磁碟間利用 DMA 進行傳輸，以此提供底層磁碟裝置全部的 I/O 頻寬。

### 確定速率 I/O

XFS 確定速率 I/O 系統給應用程式提供了預留檔案系統頻寬的 API。XFS 會動態計算底層儲存裝置能提供的效能，並在給定的時間內預留足夠的頻寬以滿足所要求的效能。此項特性是 XFS 所獨有的。確定方式可以是硬性的或軟性的，前者提供了更高效能，而後者相對更加可靠。不過只要底層儲存裝置支援硬性速率確定，XFS 就只允許硬性模式。這一機制最常被用在即時應用中，比如影片流。

### DMAPI

XFS 實現了資料管理應用程式介面（DMAPI）以支援高階儲存管理（HSM）。到 2010 年 10 月為止，Linux 上的 XFS 實現已經支援 DMAPI 所要求的的磁碟元資料規範，但有報告稱核心支援仍處於不穩定狀態。此前 SGI 曾提供了一個包含 DMAPI 勾點的核心原始碼樹，但這個支援未被合併進主代碼樹。不過現在核心開發者們已經注意到了它並對其做了更新。

### 快照

XFS 並不直接提供對檔案系統快照的支援，因為 XFS 認為快照可在卷管理器中實現。對一個 XFS 檔案系統做快照需要呼叫 `xfs_freeze` 工具凍結檔案系統的 I/O，然後等待卷管理器完成實際的快照建立，再解凍 I/O，繼續正常的操作。之後這個快照可以被當作備份，以唯讀方式掛載。在 IRIX 上釋出的 XFS 包含了一個整合的卷管理器，叫 XLV。這個卷管理器無法被移植到 Linux 上，不過 XFS 可以和 Linux 上標準的 LVM 正常工作。在最近釋出的 Linux 核心中，`xfs_freeze` 的功能被實現在了 VFS 層，當卷管理器的快照功能被喚醒時將自動啟動 `xfs_freeze`。相對於無法掛起，卷管理器也無法對其建立「熱」快照的 ext3 檔案系統，XFS 的快照功能具有很大優勢。幸運的是，現在這種情況已經改觀。從 Linux 2.6.29 核心開始，ext3, ext4, gfs2 和 jfs 檔案系統也獲得了凍結檔案系統的特性。

### 線上碎片整理

雖然 XFS 基於 Extent 的特徵和延遲分配策略顯著提高了檔案系統對碎片問題的抵抗力，XFS 還是提供了一個檔案系統碎片整理工具，`xfs_fsr`（XFS filesystem reorganizer 的簡稱）。這個工具可以對一個已被掛載、正在使用中的 XFS 檔案系統進行碎片整理。

### 線上尺寸調整

XFS 提供了 `xfs_growfs` 工具，可以線上調整 XFS 檔案系統的大小。XFS 檔案系統可以向儲存當前檔案系統的裝置上的未分配空間延伸。這個特性常與卷管理功能結合使用，因為後者可以把多個裝置合併進一個邏輯卷組，而使用硬碟分割區儲存 XFS 檔案系統時，每個分割區需要分別擴容。到 2010 年 8 月為止，XFS 分割區不可以原位收縮，不過有一些方法可以變相處理這個問題。

### 原生備份 / 恢復工具

XFS 提供了 `xfsdump` 和 `xfsrestore` 工具協助備份 XFS 檔案系統中的資料。`xfsdump` 按 inode 順序備份一個 XFS 檔案系統。與傳統的 UNIX 檔案系統不同，XFS 不需要在 dump 前被解除安裝；對使用中的 XFS 檔案系統做 dump 就可以保證鏡像的一致性。這與 XFS 對快照的實現不同，XFS 的 dump 和 restore 的過程是可以被中斷然後繼續的，無須凍結檔案系統。`xfsdump` 甚至提供了高效能的多執行緒備份操作 —— 它把一次 dump 拆分成多個資料流，每個資料流可以被發往不同的目的地。不過到目前為止，Linux 尚未完成對多資料流 dump 功能的完整移植。

### 原子磁碟配額

XFS 的磁碟配額在檔案系統被初次掛載時啟用。這解決了一個在其它大多數檔案系統中存在的一個競爭問題：要求先掛載檔案系統，但直到呼叫 quotaon (8) 之前配額不會生效。

## 效能考慮

### 寫入屏障

XFS 檔案系統預設在掛載時啟用「寫入屏障」的支援。該特性會一個合適的時間沖刷底層儲存裝置的回寫快取，特別是在 XFS 做紀錄檔寫入操作的時候。這個特性的初衷是保證檔案系統的一致性，具體實現卻因裝置而異 —— 不是所有的底層硬體都支援快取沖刷請求。在帶有電池供電快取的硬體 RAID 控制器提供的邏輯裝置上部署 XFS 檔案系統時，這項特性可能導致明顯的效能退化，因為檔案系統的代碼無法得知這種快取是非揮發性的。如果該控制器又實現了沖刷請求，資料將被不必要地頻繁寫入物理磁碟。為了防止這種問題，對於能夠在斷電或發生其它主機故障時保護快取中資料的裝置，應該以 `nobarrier` 選項掛載 XFS 檔案系統。

### 紀錄檔的放置

XFS 檔案系統建立時預設使用內建紀錄檔，把紀錄檔和檔案系統資料放置在同一個塊裝置上。由於在所有的檔案系統寫入發生前都要更新紀錄檔中的元資料，內建紀錄檔可能導致磁碟競爭。在大多數負載下，這種等級的競爭非常低以至於對效能沒有影響。但對於沉重的隨機寫入負載，比如在忙碌的資料塊伺服器上，XFS 可能因為這種 I/O 競爭無法獲得最佳效能。另一個可能提高這個問題的嚴重性的因素是，紀錄檔寫入被要求以同步方式提交 —— 它們必須被完全寫入，之後對應實際資料的寫入操作才能開始。

如果確實需要最佳的檔案系統效能，XFS 提供了一個選項，允許把紀錄檔放置在一個分離的物理裝置上。這只需要很小的物理空間。分離的裝置有自己的 I/O 路徑，如果該裝置能對同步寫入提供低延遲的路徑，那麼它將給整個檔案系統的操作帶來顯著的效能提升。SSD，或帶有寫回快取的 RAID 系統是紀錄檔裝置的合適候選，它們能滿足這種效能要求。不過後者在遭遇斷電時可能降低資料的安全性。要啟用外部紀錄檔，只須以 `logdev` 選項掛載檔案系統，並指定一個合適的紀錄檔裝置即可。

## 缺點

* XFS 檔案系統的卷無法被直接收縮，只能通過「備份 -> 重灌 -> 還原」的方式間接進行容量縮減（這也是雲端主機供應商會告知儲存空間只能增加不能縮減的其中一個原因），在準備多一組儲存卷的情況下，有工具可對 XFS 卷進行上述操作：`xfsdump` 和 `xfsrestore`。
* 歷史上 XFS 上的元資料操作曾比其它檔案系統都慢，表現為在刪除大量小檔案時效能糟糕。該效能問題是被 Red Hat 的 XFS 開發者 Dave Chinner 在代碼中定位到的。使用一個叫「延遲記錄」的掛載選項可以成數量級地提升元資料操作的效能。該選項幾乎把紀錄檔整個存在記憶體中。Linux 核心主線版本 2.6.35 中作為一個試驗性特性引入了這個修補程式，在 2.6.37 中使它成為了一個穩定的特性，並在 2.6.39 中把它作為預設的紀錄檔記錄方法。早期測試顯示在有少量執行緒的環境中其效能接近 EXT4，在大量執行緒的環境下超過了 EXT4。
* 缺少透明壓縮的支援
* 缺少校驗保護，校驗保護在對付靜態型資料損毀方面有幫助

## 參考文獻

* XFS for Linux Administration（SGI Document Number: 007-4273-003）