Btrfs - Arch Linux 中文维基

跳至內容

# Btrfs

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 Btrfs，最近一次同步於 2025-09-20，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- 文件系統
- Snapper
- Timeshift
- Yabsnap

譯自 Introduction — BTRFS Documentation：

  Btrfs 是為 Linux 開發的現代寫時複製（CoW, Copy-on-Write）文件系統，旨在提供高級功能，同時也注重容錯、修復及便於管理。

注意：與其它一些文件系統類似，Btrfs 仍在持續開發中，因此某些特定的功能可能尚未成熟到可以滿足日常使用。要檢查特定使用場景是否會受到影響，可查閱 Btrfs 官方文檔的狀態頁面（英文）及本文的#已知問題部分。

## 準備

安裝用戶空間工具 btrfs-progs包，這是執行基本操作所必需的。

若需要從 Btrfs 文件系統啟動（即內核和 initramfs 位於 Btrfs 文件系統），請檢查引導加載程序是否支持 Btrfs。

## 創建文件系統

下文展示如何創建一個新的 Btrfs 文件系統。若要將一個 ext3/4 文件系統轉換為 Btrfs，請參考 #從 ext3/4 轉換。若要使用無分區的配置，請參考 #無分區 Btrfs 磁碟。

查閱 mkfs.btrfs(8) 以獲取更多信息。

Btrfs 文件系統可建立在一個或多個設備上。此處「設備」是指 Linux 塊設備，例如整個磁碟、分區、LVM 邏輯卷、迴環設備、網絡塊設備等。

### 單設備文件系統

要在分區 `/dev/分區名` 上創建一個 Btrfs 文件系統，執行：

    # mkfs.btrfs -L 自定义卷标 /dev/分区名

Btrfs 文件系統中，元數據的默認節點大小（nodesize）為 16 KiB 和系統頁大小之中較大者，而數據的默認扇區大小等於系統頁大小（自動檢測）。如需為元數據指定更大的節點大小（必須是扇區大小的整數倍，最大允許 64 KiB），可通過 `-n` 選項來設置，如下例使用 32 KiB 的節點大小：

    # mkfs.btrfs -L 自定义卷标 -n 32k /dev/分区名

注意：根據 mkfs.btrfs(8) § OPTIONS 手冊頁內容：「較小的節點大小會增加碎片化，但B樹變得更高，從而能夠減少鎖競爭。較大的節點大小則能使數據更加緊湊並降低碎片化程度，但在更新元數據塊時需要更多昂貴的內存操作。」

### 多設備文件系統

警告：

- Btrfs 的 RAID 5 和 RAID 6 模式存在致命缺陷，除非用來做丟失數據無所謂的測試，否則不應當用於任何場景。這裡有已知問題和部分繞過方案的列表。 查閱 btrfs(5) § RAID56 STATUS AND RECOMMENDED PRACTICES 以獲取最新動態。
- 默認情況下，systemd 會為 `/var/log/journal` 目錄禁用寫時複製（CoW），這在 RAID 1 上會導致數據損壞（參見 #禁用寫時複製）。要避免這種情況，請創建一個空文件 `/etc/tmpfiles.d/journal-nocow.conf`，用來覆蓋 `/usr/lib/tmpfiles.d/journal-nocow.conf`（參閱 tmpfiles.d(5) § CONFIGURATION DIRECTORIES AND PRECEDENCE）。

Btrfs 可以在多個設備上創建 RAID。Btrfs 支持的 RAID 級別包括 RAID 0、RAID 1、RAID 10、RAID 5 和 RAID 6（詳情參閱下文 #profile）。Btrfs 的 RAID1 profile 僅保存兩個副本，內核 5.5 版本引入了 RAID1c3 和 RAID1c4，分別對應帶有3和4個副本的 RAID 1 級別。可以使用 `-d` 和 `-m` 參數分別為數據和元數據配置 RAID 級別。默認情況下，數據只有一份（ `single`），元數據則鏡像存儲（`raid1`）。這相當於 JBOD 配置——多個磁碟會被看做成一個文件系統，但文件不冗餘。更多有關如何創建一個 Btrfs RAID 卷的信息請參閱 Btrfs Wiki: 在多個設備上使用 Btrfs。

    # mkfs.btrfs -d single -m raid1 /dev/分区1 /dev/分区2 ...

必須在 `/etc/mkinitcpio.conf` 中加入 `udev`、`systemd` 或 `btrfs` 鉤子之一才能使用多設備 Btrfs 文件系統。查閱 mkinitcpio#常用鉤子以獲取更多信息。

創建好文件系統之後，建議使用下面的命令掃描並註冊多設備 Btrfs 文件系統，這樣在掛載多設備文件系統時就僅需指定其中的一個設備：

    # btrfs device scan

注意：

- 可以之後再將設備添加到多設備文件系統中，詳情請參見 Btrfs Wiki 上的這篇文章。
- 多個設備可以大小各異。但如果使用 RAID 配置存儲數據，當一個磁碟的大小比其他的加起來都大時，多出的空間並不會被使用。要確定多設備 Btrfs 的可用空間，可以使用 Btrfs 磁碟使用計算器確定。
- 有些引導加載程序不支持多設備文件系統，比如 Syslinux。
- Btrfs 不會自動從速度最快的設備讀取，因此混合使用不同類型的磁碟會導致性能表現不穩定。詳情請參閱 Stack Overflow 上的這個回答。

#RAID 小節中有關於維護多設備上的 Btrfs 文件系統的建議。

#### profile

Btrfs 使用 profile 這個概念來表示鏡像、奇偶校驗和分條，對應 RAID 術語中的「RAID 級別」（若適用）。在同一個 Btrfs 文件系統中，元數據的 profile（mkfs.btrfs(8) 的 `-m` 選項）和數據的 profile（mkfs.btrfs(8) 的 `-d` 選項）可以不一樣。

一些重要的 profile：

single
  沒有鏡像、分條和奇偶校驗，讓多個設備映射到單個文件系統中。在 mdadm 術語中被叫做 `LINEAR`。
RAID0
  沒有鏡像、分條和奇偶校驗，但允許並行訪問設備。不像傳統的 mdadm RAID 那樣要求設備大小相同。
RAID1
  鏡像，沒有分條和奇偶校驗，允許在一個設備失效的情況下恢復數據。

更多 profile 請參閱手冊 mkfs.btrfs(8) § PROFILES。

## 配置文件系統

### 寫時複製（CoW）

默認情況下 Btrfs 總是對所有文件使用寫時複製（CoW）。寫入操作不會原地覆蓋數據，而是將修改後的數據塊寫入新位置，同時更新元數據指向新位置。請參閱 Btrfs Sysadmin 相關章節了解實現細節以及其優缺點。

#### 禁用寫時複製

警告：在 Btrfs 中禁用寫時複製會禁用數據校驗和 [1] [2]，禁用數據校驗和會使 Btrfs 無法得知這些文件是否損壞。與 RAID 1（包括 profile 中的 `RAID1`、`RAID1c3` 與 `RAID1c4`）結合使用時，斷電或其他原因導致的數據損壞可能會造成副本間的數據不同步。

使用 `nodatacow` 選項掛載文件系統可禁用其上新文件的寫時複製特性。注意這只會影響新建的文件，而不會影響已有的文件。`nodatacow` 參數會禁用壓縮與數據校驗和，參閱 btrfs(5) 以了解細節。

注意：

- 根據 btrfs(5) § MOUNT OPTIONS：「在單個文件系統中，無法讓一些子卷使用 `nodatacow` 參數掛載，而其他的使用 `datacow` 參數掛載。第一個被掛載子卷的掛載參數將會應用於其他所有子卷。」
- 即使已禁用寫時複製，在特定情況下寫時複製仍然會被使用，詳見下文#仍然會觸發寫時複製的情況。

要禁用空文件或目錄中新文件（同上，不會影響其中已有文件）的寫時複製特性，請使用下面的命令：

    $ chattr +C 目录或文件路径

注意：譯自 BTRFS documentation: Attributes：「在目錄上設置此屬性時，所有新建的文件將繼承該屬性。由於實現限制，此標誌只能在空文件上設置或取消。」
提示：為目錄中已存在的所有文件禁用寫時複製可以使用下面的方法：

    $ mv /path/to/dir /path/to/dir_old
    $ mkdir /path/to/dir
    $ chattr +C /path/to/dir
    $ cp -a --reflink=never /path/to/dir_old/. /path/to/dir
    $ rm -rf /path/to/dir_old

需要保證這個過程中未使用涉及到的數據。關於此處 `--reflink=never` 參數的使用，詳見下文 #對複製的影響。

##### 仍然會觸發寫時複製的情況

具有 +C 屬性的文件仍然允許有超過一個引用（例如使用 `cp` reflink 的副本與 Btrfs 中的快照），此時寫時複製依然會生效。

本文或本章節的語言、語法或風格需要改進。參考：幫助:風格

原因：子章節嵌套過多。（在en:Talk:Btrfs討論）

###### 對複製的影響

使用 `cp` 複製文件時，+C 屬性並非由源文件決定，而取決於目標路徑——要麼從上級目錄繼承，要麼由文件系統是否使用 `nodatacow` 參數掛載決定。當源文件與目標文件都具有/不具有 +C 屬性時，能夠通過 reflink 進行複製，否則不能。實際行為依賴於 `--reflink` 參數，有以下三種結果：

- 使用 `--reflink=auto` 參數（默認情況）：若 +C 屬性相同，則使用 reflink；否則進行深拷貝。
- 使用 `--reflink`（或 `--reflink=always`）參數：若 +C 屬性相同，則使用 reflink；否則操作失敗。
- 使用 `--reflink=never` 參數：總是進行深拷貝。

總的來說，如果確實要避免寫時複製，必須顯式地使用 `--reflink=never` 參數（若目標路徑沒有 +C 屬性，先創建一個有 +C 屬性的目錄/空文件再覆蓋它）。有關 `--reflink` 參數的更多信息請參閱 cp(1)。

###### 對快照的影響

如果為禁用了寫時複製的文件創建快照，快照會鎖定當前文件的數據塊，因此首次寫入該文件的塊時會觸發寫時複製。但文件仍保留 +C 屬性，故後續對同一文件塊的寫入仍為原地操作，直至下次創建快照。

頻繁快照會減弱 +C 屬性的效果，因為在每次快照後的第一次寫入都會觸發寫時複製。要避免這種情況，可以把所有禁用寫時複製的文件放在一個單獨的子卷中並避免為該子卷創建快照。

### 壓縮

Btrfs 支持自動的透明壓縮，這不僅能縮減文件體積，還能通過減少寫入放大來顯著延長快閃記憶體介質的使用壽命，詳見 Fedora:Changes/BtrfsByDefault#Compression、[3] 與 [4]。在某些情況下（例如單線程、重文件 I/O 時），壓縮可以提升性能，而在其他場景中（如多線程和/或大文件I/O的CPU密集型任務），性能則會明顯受影響。採用快速的壓縮算法（`zstd` 和 `lzo`）通常性能也就越好。一些基準測試提供了詳細的對比數據。

#### 壓縮類型

Btrfs 支持的壓縮算法有 `zlib`（即 zlib 庫提供的 DEFLATE 壓縮算法）、`lzo`（即 LZO）和 `zstd`（即 zstd 實現的 Zstandard 壓縮算法）。其中 `lzo` 無壓縮級別，而 `zlib` 和 `zstd` 可調整壓縮級別（`zlib`：1～9；`zstd`：-15～-1、1～15，需為整數），級別越高壓縮效果越好而所需時間越長。改變壓縮級別對 CPU 和 I/O 吞吐的影響不一樣，因此在變更前後最好進行檢查和性能測試。關於壓縮類型的更多信息，可參閱 btrfs(5) § COMPRESSION。

警告：如果使用 `zstd` 算法（尤其是 -15～-1 級別），使用較舊的內核或 btrfs-progs包 的系統可能不能讀取或修復該文件系統。

#### 啟用壓縮

##### 為文件系統啟用

掛載時指定 `compress=算法[:級別]` 掛載選項，對於文件系統中每次寫入，Btrfs 將自動考慮是否啟用壓縮。其中的 `算法` 處可以填寫 `zlib`、`lzo`、`zstd` 或 `no`（即不壓縮），可選的 `級別` 處填寫壓縮級別，不填寫或填寫 0 時取默認值 3（`lzo` 不適用）。使用該選項時，Btrfs 會檢測文件寫入的數據的首個數據塊經壓縮後體積是否縮小。如果縮小，則壓縮本次寫入的全部內容，否則文件會被標記為 `NOCOMPRESS`，整個寫入過程及該文件後續的所有寫入過程都不會觸發壓縮 [5]。這是為了防止等待所有待寫入數據完全交付給 Btrfs 並進行嘗試壓縮後，磁碟才開始執行寫入操作。

注意：

- 壓縮掛載選項會在同一文件系統的所有掛載點（包括不同子卷與 bind 掛載）之間共享 [6]。
- 若文件的一次寫入無法壓縮，此後寫入均不會進行壓縮。

或者，您可以在 Btrfs 子卷上設置壓縮屬性，並且無論它如何掛載，它都會持久化並應用，使用 `btrfs property set / compression alg`，其中 `alg` 可以是 `zstd` 或 `zstd:n`，其中 `n` 是壓縮級別。

這篇文章的某些內容需要擴充。

原因：下文陳述的有關試驗測試的結果缺少引用來源，且此處關於百分比的原文表述並不準確（故譯文不一定正確）。 (在 Talk:Btrfs 中討論)

若改用 `compress-force=算法[:級別]` 掛載選項，Btrfs 會檢查每次寫入的每個數據塊並分別決定是否壓縮。在多個混合用途系統上進行的經驗測試表明，使用 `compress-force=zstd` 相比使用 `compress=zstd` 能顯著提高空間節省率（從 10% 提升到 20%），但這會導致 CPU 占用率無端（略微）升高且拖長寫入所需時間。官方 Btrfs 指導手冊不推薦使用該選項。

使用 `compress-force` 也會限制 extent 的最大大小，從而增加碎片化。[1]

只有在添加以上兩個掛載選項之一後新建或修改的文件才會被自動壓縮。

提示：在新的 Btrfs 上安裝 Arch Linux 時，如果需要將其壓縮後存儲，需要在系統安裝前就使用 `compress` 選項掛載，例如：`mount -o compress=zstd /dev/sdxY /mnt/`，並注意在其 fstab 中為根目錄文件系統指定相同的 `compress` 掛載選項。

##### 為現有文件啟用

要為現有文件啟用壓縮，可使用 `btrfs filesystem defragment -c算法` 命令，`算法` 處可選填為 `zlib`、`lzo` 或 `zstd`，使用 `-L` 選項指定壓縮級別，否則使用默認值 3（`lzo` 不適用）。例如，執行以下命令可用 `zstd` 的 1 壓縮級別重新壓縮所有文件：

    # btrfs -v filesystem defragment -r -czstd -L1 /

警告：defragment 操作會斷開 #寫時複製（CoW）數據（包括通過 `cp` 複製的文件、#快照和#去重數據等）之間的 reflink，產生獨立的文件，可能顯著增加空間使用量 [7]。

使用上面的方式壓縮文件不會被持久化，其他寫入操作將應用原有壓縮設置。

以下兩種方式可以持久性啟用對單個文件的壓縮：

    $ chattr +c 文件

    $ btrfs property set 文件 compression zstd

前一條命令使用的是從 ext2 文件系統繼承的文件屬性舊接口，靈活性不足，只能夠使用默認的 `zlib` 壓縮算法。後一條命令則可以指定壓縮算法，但指定壓縮級別尚未實現，因此採用默認值 3（`lzo` 不適用）。

#### 查看壓縮類型和壓縮率

compsize包 接收一個包含文件或目錄（可為整個 Btrfs 文件系統）的列表，輸出其使用的壓縮類型以及實際壓縮率（壓縮後大小/壓縮前大小）。壓縮前大小可能與其他程序（如 du(1)）顯示的數值不一致，因為每個 extent 都會被統計且只統計一次⸺即使有多個 reflink，或其部分內容已不再使用但尚未被垃圾回收。

`-x` 選項可限制在單一文件系統內執行，這在類似於 `compsize -x /` 的場景中非常有用，可以避免程序因嘗試訪問非 Btrfs 的子目錄而導致整個運行的失敗。

### 子卷

「Btrfs 子卷是可獨立掛載的 POSIX 文件樹，而不是也不能看作是塊設備。大多數其他 POSIX 文件系統只有一個可掛載根，而 Btrfs 不僅整個卷（稱作『頂層子卷』）可以掛載，每個子卷也可獨立掛載；一個 Btrfs 卷可以包含不止一個文件樹⸺包含一個『文件森林』。Btrfs 子卷可以理解為一個 POSIX 文件命名空間。」[8]

每個 Btrfs 文件系統都有一個 ID 為 5 的頂層子卷。這個子卷不能被移除或被其他子卷替代。頂層子卷在文件系統中的路徑為 `/`，其他子卷則嵌套在頂層子卷之下。子卷（不包括頂層子卷）可以在文件系統中移動，其路徑可以發生變化，但子卷 ID 不可更改。

默認情況下，掛載文件系統時會掛載頂層子卷。可以通過選項來掛載指定子卷。

子卷的主要用途之一是#快照。

更多詳細信息請參閱以下連結（英文）：

- Btrfs 文檔
- Btrfs Wiki SysadminGuide#Subvolumes
- Btrfs Wiki Trees

#### 創建子卷

要創建子卷，必須先掛載該 Btrfs 文件系統以使其要創建的路徑可以訪問（掛載根子卷或者上級子卷）。

    # btrfs subvolume create 路径/子卷名

例如，在 `/mnt` 所在子卷下創建子卷 `@sub`（路徑為 `/mnt/@sub`）：

    # btrfs subvolume create /mnt/@sub

注意：

- 使用 `-p`（`--parents`）選項可以自動創建不存在的父目錄。
- Btrfs 中子卷名可以是任何有效的目錄名，以 `@` 符號開頭只是timeshift包的命名約定。
- 如果頂層子卷沒有掛載，而你想在其內部創建子卷，可以通過指定 `subvolid=5` 來臨時掛載它。參見 #掛載子卷。

#### 列出子卷

查看`路徑`所屬文件系統的所有子卷列表：

    # btrfs subvolume list -t 路径

使用 `-t` 選項會顯示更易讀的表格視圖。

#### 刪除子卷

刪除子卷：

    # btrfs subvolume delete 子卷路径

如果子卷包含其他子卷，需要添加 `-R`（`--recursive`）選項來遞歸刪除包含的所有子卷。子卷也可以當作常規目錄刪除（使用 `rm -r`、`rmdir`；但這樣會比較慢）。

#### 掛載子卷

使用`subvol=子卷路徑（相對於頂層子卷）`或`subvolid=子卷ID`選項來掛載子卷。通過在文件系統的頂層創建各種子卷，然後將其掛載到適當的掛載點，可以模擬傳統的文件系統分區。

例如，以下將頂層子卷掛載到 `/mnt/` 並創建兩個名為 `subvol_root` 和 `subvol_home` 的子卷。當頂層子卷被卸載時，新的子卷將被掛載到 `/mnt/` 和 `/mnt/home/`：

    # mount device /mnt/ -o subvolid=5
    # btrfs subvolume create /mnt/subvol_root/
    # btrfs subvolume create /mnt/subvol_home/
    # umount /mnt/
    # mount -o subvol=/subvol_root device /mnt/
    # mount -o subvol=/subvol_home --mkdir device /mnt/home/

使用 `subvol` 掛載選項引用子卷時，需要使用相對於「頂層子卷」的路徑。

提示：

- 子卷 ID 可通過#列出子卷顯示。
- 不將頂層子卷作為 `/` 掛載會使更改子卷布局的更加簡單。因此，考慮創建一個子捲來作為 `/` 掛載（用以存放你的系統文件）。

注意：譯自 btrfs(5) § MOUNT OPTIONS：「大多數掛載選項適用於整個文件系統，因而只有第一個掛載的子卷的選項才會生效。這是由於尚未實現分子卷的選項處理，將來情況可能會改變。這意味著（例如）你無法使用掛載選項為每個子卷單獨設置 `nodatacow`、`nodatasum` 或 `compress`。這最終應該會被修復，但事實證明在 Linux VFS 框架內正確實現是困難的。」

有關目前及計劃可以為每個子卷單獨應用的掛載選項，請參閱 Btrfs Wiki FAQ。

提示：最好使用 `subvol=/path/to/subvolume` 來掛載，而不是使用 subvolid，因為在恢復 #快照 時，subvolid 可能會發生變化，從而需要更改掛載配置。

請參閱 Snapper#建議的文件系統布局、Btrfs SysadminGuide#Managing Snapshots 和 SysadminGuide#Layout，了解使用子卷的文件系統布局的例子。

有關 Btrfs 特有的掛載選項的完整列表，請參閱 btrfs(5) § BTRFS SPECIFIC MOUNT OPTIONS。

#### 將子卷掛載為 /

如果要將子卷掛載為 `/`，要麼#更改默認子卷，要麼在 `rootflags` 內核參數中指定掛載子卷的選項（一些引導加載程序可以自動添加，例如 GRUB 的 `grub-mkconfig` 命令），並編輯 `/etc/fstab`。建議使用 `subvol=子卷路徑` 而不是 `subvolid` 來掛載，因為後者可能在恢復#快照之後發生變化，如果不同時更改掛載選項，系統將不能啟動。

如果你計劃使用其中一種同步和備份程序，建議不要更改默認子卷，因為它會在恢復除默認子卷之外的其他子卷的快照時導致問題。例如，Timeshift會相對於文件系統的默認子卷創建一個路徑`timeshift-btrfs`來存儲快照，並且建議為根和家目錄使用一個單獨的非默認子卷。

#### 更改默認子卷

如果沒有提供 `subvol` 與 `subvolid` 選項，將掛載默認子卷。要將指定子卷設置為所在文件系統的默認子卷，執行：

    # btrfs subvolume set-default 子卷路径

或者使用：

    # btrfs subvolume set-default 子卷ID 路径

將`路徑`所在文件系統的默認子卷設置為 ID 為`子卷ID` 的子卷。

提示：子卷ID可通過#列出子卷顯示。

使用 `btrfs subvolume set-default` 更改默認子卷後，頂層子卷需要使用 `subvol=/` 或 `subvolid=5` 掛載選項掛載 [9]。

注意：

- GRUB 的 `grub-mkconfig` 腳本不遵守 Btrfs 的默認子卷設置⸺如果 `/` 是頂層子卷，始終不會指定 `subvol=/` 或 `subvolid=5` 掛載選項，可能導致無法啟動；如果 `/` 非頂層子卷，始終會指定相應的 `subvol` 選項，導致無法僅通過設置默認子卷回退（bug 報告）。目前可以通過手動修改 `grub.cfg` 中 `rootflags` 內核參數解決（參見 #掛載子卷），或者使用工具自動在 GRUB 中為快照創建啟動項（參見 #引導進入快照）。另外，如果 `grub.cfg` 的實際位置發生改變，例如包含 `/boot` 的子卷改變，需要再次運行 `grub-install`。詳見這個論壇帖子。
- 如果你打算使用某個同步和備份程序，不推薦更改默認子卷，以免在恢復非默認子卷的快照時出現問題。例如Timeshift會在默認子卷下創建路徑`timeshift-btrfs`來儲存快照，為/和/home使用單獨的非默認子卷比較好。

### 配額

磁碟配額的概念在Unix世界有著悠久的傳統。傳統配額基於文件所有權，通過限制用戶擁有的所有文件的總大小來控制空間使用。Btrfs採用了與傳統Unix系統不同的配額設計理念，不支持傳統的基於用戶或用戶組的配額功能，這是因為其現代存儲特性（如#快照、#寫時複製（CoW）、#去重和#壓縮）使得傳統配額的空間計算變得極其複雜且不準確 [10]。作為替代，Btrfs 採用基於子卷的配額機制，現提供兩種實現機制⸺傳統的#配額組和較新的#簡單配額（在2023年底發布的6.7版本內核中引入）來實現類似的空間管理效果。雖然增加了管理複雜性，但提供了更靈活和精確的存儲控制能力，且不用分區即可限制目錄大小，支持動態調整配額。

注意：掛載Btrfs文件系統（或其中任一子卷）後才可以管理配額。

#### 配額組

警告：

儘管Btrfs 配額組（quota group，簡稱 qgroup）在常規使用中被認為是穩定的，但啟用配額組功能，尤其是在頻繁創建大量快照的環境中，仍可能導致性能下降，特別是在刪除快照時。配額組統計會引入額外的元數據開銷，並可能在高強度快照工作負載下影響系統響應速度。

近期的內核改進（5.15及後續版本）已修復諸多歷史問題，但某些限制依然存在，特別是在深度嵌套的子卷或複雜的配額組層級結構等高級應用場景中。2016年就寫在這裡的建議⸺啟用配額組前需審慎評估具體使用場景，至今仍然適用。請務必查閱最新的 Btrfs 文檔獲取當前詳細信息。值得注意的是，為了解決配額組的性能問題，Btrfs引入了#簡單配額功能，提供了靈活性略差但性能更優的替代方案。

Btrfs精確的配額支持是通過子卷之上的配額組實現的。配額組使用配額組ID（qgroupid）表示，格式為`層級/ID`。子卷的層級是0，`0/` 可以省略，而子卷對應的 `ID` 就是子卷的 ID，例如 `0/5` 表示頂層子卷的配額組，也可以用子卷路徑代替 `0/ID` 的表示方式。配額組形成「樹」狀層級結構，但一個配額組可以有多個父配額組 [11]。葉子配額組層級為0，即子卷直接對應的配額組。所有更高層級配額組的 `ID` 可以自由指定。高層級配額組包含低層級配額組，相同層級之間不可嵌套，但層級不表示嵌套深度。例如，可以為 `5/100` 配額組分配子配額組 `0/5`。

##### 總引用空間和獨占引用空間

每個配額組主要追蹤兩個數值：總引用空間（total referenced space）和獨占引用空間（exclusively referenced space）。其中總引用空間是指所有能夠從配額組內訪問到的數據占用的存儲空間，獨占引用空間是指只被配額組所屬的子卷引用（而不被該配額組以外的子卷引用）的數據所占用的存儲空間。

##### 啟用/禁用配額組

使用以下命令為`路徑`所在文件系統啟用配額組：

    # btrfs quota enable 路径

將 `enable` 改為 `disable` 以禁用配額組。

警告：禁用配額組會銷毀當前所有配額組並解除其關係。

##### 創建/銷毀配額組

子卷對應的0層級配額組始終會自動創建。即便子卷在啟用配額前創建，啟用配額時也會自動創建相應配額組。同樣，#刪除子卷時子卷對應的配額組也會被刪除，並自動解除與原包含有這一配額組的高層級配額組的關係。

使用以下命令在`路徑`所在文件系統創建配額組`層級/ID`：

    # btrfs qgroup create 层级/ID 路径

將 `create` 改為 `destroy` 以銷毀配額組。銷毀配額組類似於使用 `rm -d` 刪除目錄⸺如果配額組存在子配額組，必須先解除關係；如果僅存在父配額組，關係會自動解除。

注意：子卷對應的配額組不能直接刪除，而應該通過直接刪除子捲來自動刪除。

##### 分配/刪除子配額組

使用以下命令將`路徑`所在文件系統的`子配額組`分配到`父配額組`，注意`父配額組`必須比`子配額組`層級更高：

    # btrfs qgroup assign 子配额组 父配额组 路径

將 `assign` 改為 `remove` 以解除這一關係。

注意：分配/解除分配子配額組後可能需要 #配額重掃描，這在當前版本中會自動觸發，但可能造成性能消耗，詳見#配額重掃描章節。

##### 限制/取消限制配額組

可以限制配額組的總引用空間或獨占引用空間，或同時限制兩者。例如，使用以下命令在`路徑`所在文件系統中限制`配額組`的總引用空間不超過 1 GiB：

    # btrfs qgroup limit 1G 配额组 路径

注意：如果已#啟用壓縮，Btrfs目前僅支持限制壓縮後的數據占據的空間。

其中`配額組`若省略，則會嘗試將`路徑`解釋為子卷路徑。添加選項 `-e`（到 `limit` 之後）改為限制獨占引用空間。將`大小限制`改為`none` 以取消限制。

##### 列出配額組

使用以下命令列出`路徑`所在文件系統的所有配額組：

    # btrfs qgroup show 路径

注意：由於 `btrfs qgroup show` 使用的是磁碟中的數據，可能需要 `sync` 後才能顯示準確的統計數據。為此可以添加 `--sync` 選項（到 `show` 之後），先對`路徑`所在文件系統執行強制同步操作。

輸出的「Path」列可能顯示一些特殊值，含義如下：

- `<toplevel>`：頂層子卷對應的配額組。
- `<under deletion>`：該配額組對應子卷已被刪除（其目錄已移除），但子卷元數據尚未完全清理。

提示：可以使用 `btrfs subvolume sync 路徑 子卷ID` 等待`路徑`所在文件系統中子卷完全刪除（可以指定多個子卷 ID；若一個也沒有指定則等待當前文件系統中所有待刪除子卷刪除完畢）。但請注意先卸載該子卷。

- `<squota space holder>`：（僅適用於 #簡單配額）該配額組對應子卷已完全刪除但相關統計信息仍保留。這是由於簡單配額只將extent歸屬於首次分配它的子卷，而該子卷已完全刪除但extent仍被其他子卷引用。

根據需求，可以添加一些顯示選項（到 `show` 之後）。常用的選項有：

- `-p`：顯示父配額組。
- `-c`：顯示子配額組。
- `-r`：顯示總引用空間限制。
- `-e`：顯示獨占引用空間限制。
- `-f`：僅列出`路徑`所在子卷對應的配額組。
- `-F`：僅列出`路徑`所在子卷對應的配額組及包含這些配額組的高層級配額組。

更多選項請參閱 btrfs-qgroup(8) § show。

##### 配額重掃描

配額重掃描（quota rescan）會讀取文件系統中所有extent的元數據，據其更新各配額組的統計值。

Btrfs的配額組可以處理許多複雜的extent共享和不再共享場景（包括子卷、子配額組的刪除），同時保持總引用空間與獨占引用空間的準確計數。但當配額組關係發生變化（手動 #分配/解除分配子配額組）時，由於記錄的數據不足（僅記錄總引用空間與獨占引用空間，而未明確記錄哪些extent屬於共享或獨占），通常需要在整個文件系統內配額重掃描，此時配額組會被標記為「inconsistent」（不一致），即需要配額重掃描的狀態。

目前實現中唯一的例外是配額組的總引用空間等於獨占引用空間（即所有數據都為獨占）時，僅需要在父配額組的總引用空間與獨占引用空間上同時加上/減去該配額組的引用空間，不需要重新掃描配額。

自4.19版本內核起，手動#分配/解除分配子配額組時會自動觸發配額重掃描（除了以上例外情況）。但考慮到其開銷較大、同時只能進行一個操作、無法等待重掃描結束後再返回，可以在 `assign`/`remove` 之後添加 `--no-rescan` 選項以避免自動觸發重掃描，轉而在之後再手動觸發。

提示：使用 `--no-rescan` 選項#分配/解除分配子配額組後，若需要配額重掃描，會顯示相應警告。也可以通過#列出配額組顯示警告。

使用以下命令手動觸發重新掃描`路徑`所在文件系統的配額：

    # btrfs quota rescan 路径

命令運行後立即返回，添加 `-w`（`--wait`）選項（到 `rescan` 之後）以等待重新掃描結束（即使已開始）再返回。使用 `-W`（`--wait-norescan`）選項僅等待當前正在運行的重新掃描結束。使用 `-s`（`--status`）選項返回當前進度。

#### 簡單配額

#配額組可以處理許多複雜的extent共享和不再共享場景（包括子卷、子配額組的刪除），同時維護總引用空間與獨占引用空間的準確計數，但這種靈活性是有代價的：許多計算操作具有全局性，即當extent引用關係變更後，會影響到引用該extent的所有配額組的統計值。這可能導致事務提交速度下降並引發不可接受的延遲，尤其在快照數量激增的情況下更為明顯。

為解決配額組的這一局限，Btrfs還支持另一套配額規則體系：簡單配額（simple quota，簡稱squota）。簡單配額復用了配額組的API和層次結構模型，但不追蹤共享與獨占使用情況。相反，簡單配額將所有extent歸屬於首次分配它的子卷。通過引入少量新的元數據記錄，這樣所有核算決策都能在涉及數據塊本身的分配或釋放操作的局部完成，完全避免了複雜且耗時的反向引用解析過程。

簡單配額需要在文件系統級別啟用，在啟用配額組的命令中添加 `-s`（`--simple`）選項（到 `enable` 之後）即可。注意若配額組已經開啟，需要先禁用配額組再啟用簡單配額，否則不會生效 [12]。由於其簡單的計算方法，簡單配額模式下不需要（也不能）進行#配額重掃描。除了這兩點外，簡單配額的操作方式與配額組完全相同，但顯示與限制使用的所謂「總引用空間」和「獨占引用空間」都是通過上文所述方法（將所有extent歸屬於首次分配它的子卷）計算得到的值。由於簡單配額需要記錄首次分配extent的子卷，因此僅對啟用後寫入的extent生效，若在非空文件系統中啟用簡單配額，剛啟用時統計值會是0，因此只有在空子卷啟用簡單配額限制後再寫入數據，才能確保統計準確。

### 提交間隔

Btrfs 默認設置 30 秒的事務提交（commit）間隔，即每 30 秒將新數據從內存同步到永久存儲。可通過 `commit` 掛載參數（單位為秒）更改，例如修改 fstab：

    LABEL=arch64 / btrfs defaults,noatime,compress=lzo,commit=120 0 0

Btrfs 層面的周期性提交並非事務提交的唯一機制，該操作也可通過 `sync` 命令顯式觸發，或通過影響全局文件系統狀態的其他命令間接觸發，事務提交的機制還包括基於各類閾值或策略（如控制組）進行刷新的內核機制，這超出了本文的範圍，因此不再贅述。

### 固態硬碟數據塊異步丟棄

TRIM 或丟棄（discard）數據塊是指文件系統通知固態硬碟哪些數據塊不再使用的操作，從而固態硬碟能夠在空閒時擦除（回收）這些數據塊，避免等到需覆蓋時再進行。內核 6.2 版本起默認啟用異步丟棄功能：extent在釋放事務提交後不會立即觸發丟棄其包含的數據塊，而是由獨立的工作線程分組後統一進行，從而改善提交延遲。

異步丟棄可以與定期 TRIM 一同使用 [13]。

有關 TRIM 的更多信息，請參閱固態硬碟#TRIM。

## 使用

### 查看空間使用情況

因為不能同時考慮文件和元數據的使用情況，df(1) 之類的通用用戶空間工具在 Btrfs 上並不能準確地報告剩餘空間大小。推薦使用 `btrfs filesystem usage` 來查看空間使用情況，例如：

    # btrfs filesystem usage /

或者使用 `btrfs filesystem df` 快速檢查已分配空間及其使用情況，無需 root 權限：

    $ btrfs filesystem df /

注意：對於 #多設備文件系統，在 `RAID5` 或 `RAID6` #profile 與其它 profile 共存於同一文件系統時（例如，元數據使用 `DUP` 而數據使用 `RAID5`），`btrfs filesystem usage` 和 `btrfs filesystem df` 顯示出的空間使用情況不準確 [14]。

更多信息可參閱 [15]。

因為不考慮 #寫時複製（CoW）和透明 #壓縮，du(1) 和 ncdu(1) 之類的文件空間使用情況分析工具的數據也不準確。可考慮改用 btduAUR 或 compsize 等支持 Btrfs 特性的工具。

### 碎片整理

文件碎片整理是指嘗試通過讓文件包含的extent分布更加連續，合併小的extent，從而更有效地存儲文件的過程。

由於 Btrfs 的 #寫時複製（CoW）設計，修改文件時使用的新數據塊在物理設備上可能與原數據塊相距很遠，造成文件的碎片化。碎片化在機械硬碟上是嚴重的問題，因為移動磁頭到較遠位置會導致延遲。對於現代沒有這種延遲的設備（如固態硬碟）來說，這不再是問題，但進行碎片整理仍有意義，可以減少追蹤分散extent所需的元數據大小。

可以安全地碎片整理使用中的文件數據，但更難達到最優分布。

警告：碎片整理會斷開#寫時複製（CoW）數據（包括通過 `cp` 複製的文件、#快照和#去重數據等）之間的 reflink，產生多份獨立的數據，可能顯著增加空間使用量 [16]。

#### 手動

使用 `btrfs filesystem defragment` 命令手動進行碎片整理，例如碎片整理根目錄下的文件（不進入子卷、掛載點及到目錄的軟連結）：

    # btrfs filesystem defragment -r /

注意：不使用 `-r` 參數則碎片整理不會遞歸進行，但會對某些內部樹⸺區段樹（extent tree）和子卷樹⸺進行碎片整理。這種設計容易引發混淆，未來版本可能會取消。
提示：可以使用 `-c`、`-L` 參數指定壓縮方式，參見壓縮章節中 #為現有文件啟用部分。

#### 自動

使用掛載參數 `autodefrag` 啟用自動碎片整理，參見 btrfs(5) § MOUNT OPTIONS。

### scrub

scrub文件系統或設備是指驗證其中所有數據和元數據的過程，能夠檢測數據校驗和錯誤、基本超級塊錯誤、基本元數據塊頭錯誤以及磁碟讀取錯誤。

注意：運行中的檢修任務會阻止系統掛起，詳見該討論。

#### 手動啟動

使用以下命令在後台啟動 scrub 任務（此處「設備」指 Linux 塊設備）：

    # btrfs scrub start 路径或设备

如果指定路徑，則 scrub 路徑所在的文件系統；如果指定設備，則 scrub 該設備。

注意：在使用鏡像塊組 #profile（如 RAID1）的 #多設備文件系統上，scrub 操作還會通過從其他副本複製已驗證完好的數據來自動修復任何損壞。

檢查該任務的運行狀態：

    # btrfs scrub status /

也可以通過啟動 `btrfs-scrub@.service` 來手動運行 scrub (使用同樣的轉移後路徑)，相較 (以 root 用戶身份運行) `btrfs scrub`，這麼做的優點是輸出內容會記錄在 Systemd 日誌中。

#### 自動

btrfs-progs包 軟體包帶有 `btrfs-scrub@.timer` 系統單元，用來每月運行 scrub 命令。通過添加掛載點的參數來啟用它，例如`btrfs-scrub@-.timer` (`/`) 或者 `btrfs-scrub@home.timer` (`/home`)。你可以使用`systemd-escape -p /path/to/mountpoint`來轉義路徑，參見systemd-escape(1)。

### balance

『balance 將會通過分配器再次傳遞文件系統中的所有數據。它主要用於在添加或刪除設備時跨設備重新平衡文件系統中的數據。如果有設備出現故障，balance 將為指定的冗餘 RAID 級別重新生成缺失的副本』[17]。參閱上游的 FAQ。

在單設備文件系統上，balance 對於（臨時）減少分配但未使用（元）數據塊的數量也是有用的。有時候這對於解決 "filesystem full" 故障來說也是必須的。為減少無法分配出元數據塊組的可能，不建議對元數據進行 balance 操作，可指定如 `-dusage=30`只對數據塊組操作。

    # btrfs balance start --bg /
    # btrfs balance status /

### 交換文件

注意：

Btrfs 與 Linux 交換子系統的實現導致一些限制 [18]：

- 不支持在跨設備的文件系統上使用交換文件
- 數據 #profile 需為 `single`
- 不能為含有正在使用中的交換文件的子卷創建快照
- 交換文件必須預分配（即無空洞）
- 必須單獨為交換文件 #禁用寫時複製（即交換文件必須有 `+C` 屬性）

其中後兩個對交換文件的限制 `btrfs filesystem mkswapfile` 命令會自動處理。

交換文件的介紹參見 Swap#交換文件。

在 Btrfs 中創建交換文件的正確方法是首先創建一個子卷存儲交換文件，因為隨後無法為該子卷創建快照。例如創建 `/swap` 子卷：

    # btrfs subvolume create /swap

提示：考慮直接在頂層子卷下 #創建子卷，然後 #掛載子卷到 `/swap`（或其他可訪問路徑）。

在 `/swap/` 中創建一個 4 GiB 的交換文件 `swapfile`：

    # btrfs filesystem mkswapfile --size 4g --uuid clear /swap/swapfile

`--size` 選項指定交換文件大小，默認為 2 GiB，最小 40 KiB。

啟用交換文件：

    # swapon /swap/swapfile

最後編輯 fstab，添加交換文件的配置：

    /etc/fstab

    /swap/swapfile none swap defaults 0 0

更多信息參見 fstab#用法。

有關刪除交換文件等更多信息請參閱 Swap#交換文件。

提示：若要使用休眠功能，除了配置交換文件外，還需要完成電源管理/掛起與休眠中描述的額外步驟。

### RAID

Btrfs 提供對 RAID #多設備文件系統的原生支持。相較於使用 mdadm，其顯著優勢包括自修復冗餘陣列和在線數據平衡。更多信息請參見該 Btrfs Wiki 頁面。Btrfs SysadminGuide 提供了一些更具技術性的背景信息。

警告：奇偶校驗 RAID（RAID 5/6）代碼中存在多個嚴重的數據丟失漏洞。更多信息請參閱 Btrfs 文檔的 RAID 5/6 頁面（英文）以及 linux-btrfs 郵件列表中關於此問題的錯誤報告。2020 年 6 月，有用戶在上述郵件列表中整理髮布了當前問題的完整清單及實用的恢復指南。

### 快照

"快照是和其它子卷共享數據和元數據的簡單子卷, 利用了 btrfs 的寫時複製特性。" 詳見 Btrfs Wiki SysadminGuide#Snapshots 和 the Btrfs documentation。

要創建一個快照:

    # btrfs subvolume snapshot source [dest/]name

`source`為要創建快照的對象，`[dest/]name`為快照安放路徑。

加入 `-r` 參數可以創建一個只讀快照. 為只讀快照創建一個快照可以獲得一個只讀快照的可寫入版本.

注意：

- 將一個只讀快照通過`btrfs property set -f -ts '/path/to/snapshot' ro false`原位轉換為可寫快照是可能的。但並不推薦這樣做，因為之後任何增量發送/接受（send/receive）操作會造成問題。創建一個新的可寫快照可以預防這類問題。
- 快照不是遞歸包含的，這意味著子卷內的子卷在快照裡是空目錄。

### 發送和接收

可以通過 `send` 命令發送一個快照,通常會與 btrfs 中的 `receive` 組成管道.例如將快照 `/root_backup` (也許是`/`的備份) 發送到 `/backup`:

     # btrfs send /root_backup | btrfs receive /backup

只能發送只讀快照,上面的命令在將子卷複製到外部設備 (例如備份驅動器) 時會很有用。

接受結束後將創建對應子卷，無需手動再創建。

還有一個例子創建了`/mnt/arch-v2/subvolumes/@var`子卷：

    # btrfs send --proto 2 --compressed-data '/mnt/arch/snapshots/@var' | btrfs receive '/mnt/arch-v2/subvolumes/'

參數`--proto 2`和`--compressed-data`在本例中能夠更有效地發送快照（假設數據可壓縮）。

也可以只發送兩個快照間發生變化的部分,例如如果你已經發送了快照 `root_backup` ,然後又建立了一個新的只讀快照 `root_backup_new` ,可以這樣完成增量發送:

     # btrfs send -p /root_backup /root_backup_new | btrfs receive /backup

現在你 `/backup` 的快照會是 `root_backup_new`。

參閱 Btrfs Wiki 上關於增量備份的頁面 (英文) 獲得更多信息 (例如使用工具自動化這一過程)。

### 去重

使用寫時複製，Btrfs 能夠複製文件或整個子卷而無需實際複製數據。但是，無論何時更改文件，都會創建一個新的「真正的」副本。重複數據刪除更進一步，通過主動識別含有相同內容的數據塊並將它們通過 CoW 合併到同一個extent內。

專用於 Btrfs 分區去重的工具包括 duperemove包和bees包。也許你還希望基於文件的級別對數據進行重複數據刪除，比如 rmlint-git包、rdfind包、jdupesAUR 或者 dduper-gitAUR。有關這些程序的可用功能的概述和其他信息，請參閱上游 Wiki 條目 (英文)。

### 調整大小

警告：為避免數據丟失，確保在調整大小前備份好你的數據。

你可以增加文件系統的大小到設備的最大可用空間，或到一個指定大小。確保你在嘗試增加文件系統大小前設備或邏輯卷有足夠空間。 當指定一個設備上的文件系統到指定大小時，不論增加或減少，確保新的大小滿足下面的條件：

- 新的大小必須大於已有數據的大小，否則會導致數據損失。
- 新的大小必須等於或小於當前設備的可用空間。

注意：如果你還計劃減小文件系統所在的邏輯卷大小，請先減小文件系統大小後再嘗試減小邏輯卷的大小。

將文件系統擴展到設備的最大可用大小：

    # btrfs filesystem resize max /

將文件系統擴展到特定大小：

    # btrfs filesystem resize size /

將 `size` 替換為你需要的大小（按字節計算）。也可以為大小指定單位，如K（千字節），M（兆字節）或G（吉字節）。 或者也可以通過在大小前添加前綴指定增加（+）或減少（-）的變化量：

    # btrfs filesystem resize +size /
    # btrfs filesystem resize -size /

## 已知問題

一些在嘗試之前應該知道的限制。

### 加密

Btrfs 暫未內置加密支持，但當前正進行一項基於 Fscrypt（英語：Fscrypt） 的加密集成工作 [19]。

不過用戶仍可在運行 `mkfs.btrfs` 前加密分區，具體參見 dm-crypt/加密整個系統。另一種方案是採用棧式文件系統加密。

### 檢查 btrfs 文件系統問題

`btrfs check` 工具目前有一些已知問題，在繼續深入閱讀了解之前，您不應該直接運行它, 參見 #檢查 Btrfs 文件系統小節。

## 提示和技巧

### 無分區 Btrfs 磁碟

警告：這種配置不建議用於啟動設備，推薦設置一個單獨的EFI 系統分區和Btrfs分區。 此外，GRUB 強烈反對安裝GRUB到無分區磁碟。

Btrfs 能占用整個存儲設備，使用子卷模擬分區表來替代 MBR 或 GPT 分區表。雖然無分區磁碟不需要使用其它方法創建分區，然後在一個分區上創建 Btrfs 文件系統，但在單個磁碟上使用無分區配置存在一些限制：

- 不能在同一磁碟上的不同分區上創建其它的文件系統。
- 受上一條影響，無法在該磁碟上創建EFI 系統分區。需要額外的儲存設備用於 UEFI 啟動。

運行下面的命令把整個設備的分區表替換成 Btrfs:

    # mkfs.btrfs /dev/sdX

如果設備上存在分區表，則需要使用：

    # mkfs.btrfs -f /dev/sdX

例如， 指定`/dev/sda` 而不是 `/dev/sda1`。後一種形式會格式化現有的分區而不是替換掉原有的分區表。由於根分區是 Btrfs 文件系統，請確保已將 `btrfs` 編譯進內核, 或者將 `btrfs` 放入 Mkinitcpio#模塊（MODULES）中並且重新生成 initramfs。

像使用普通的 MBR 分區表存儲設備一樣安裝引導加載程序, 參考 Syslinux#手動安裝或 GRUB/技巧和竅門#安裝到分區上或者無分區磁碟上。 如果你的內核因為 `Failed to mount /sysroot.` 錯誤無法啟動, 請在 `/etc/default/grub` 裡添加 `GRUB_PRELOAD_MODULES="btrfs"` 並重新生成 GRUB 配置文件 。

### 從 Ext3/4 轉換

警告：Btrfs 的郵件列表中報告了多起轉換不完整/損壞/失敗的案例。在開始之前請確定您有可用的備份並且願意承擔丟失數據的風險。 參見Btrfs維基的Convert頁。

從安裝 CD 啟動，然後轉化分區：

    # btrfs-convert /dev/partition

掛載轉換後的分區並修改 `/etc/fstab` 文件，指定分區類型 (type 為 btrfs，並且 fs_passno[最後一列] 要修改為0，因為 Btrfs 在啟動時並不進行磁碟檢查)。 還要注意的是分區的 UUID 將有改變，所以使用 UUID (指定分區) 時，請更新 fstab 中相應的條目。 `chroot` 到系統並重建你的引導加載程序（如果對此過程不熟悉，參考從現有 Linux 發行版安裝 Arch Linux )。 如果轉換了根文件系統，還需要在 chroot 環境中重建初始化內存檔以確保系統正確啟動。

注意：

- 如果轉換過程中有任何異樣，不管是無法掛載新轉換的 Btrfs 文件系統或是無法往其中寫入數據，只要備份子卷 `/ext2_saved` 還在，就可以進行回滾。請使用 `btrfs-convert -r /dev/partition` 命令進行回滾，這將會丟棄任何對新轉換 Btrfs 文件系統的更改。
- 如果掛載已轉換的 ext 分區時出現如下錯誤：`ERROR: dev extent devid 1 physical offset XXX len XXX is beyond device boundary XXX`，那麼在分區末尾預留一些空閒空間後，轉換可能會成功。請先回滾轉換，然後使用 `resize2fs` 將分區縮小 50000 個塊，再擴大 5000 個塊（從而創建出 45000 個空閒塊）。然後再次嘗試轉換。參見 上游 bug 報告。

確認沒有問題後，通過刪除 `ext2_saved` 備份子卷完成轉換的最後一步。請注意，如果沒了它 (備份子卷)，你將沒辦法還原回 ext3/4 文件系統。

    # btrfs subvolume delete /ext2_saved

最後通過數據平衡回收空間。

別忘了先前安裝的一些應用需要額外設置來適配Btrfs。

注意：Ext3/4 轉換到 Btrfs 的過程很耗時。一個普通機械硬碟上的4TB文件系統轉換耗時可高達10小時。

### 從 NTFS 轉換

使用 ntfs2btrfsAUR 或 ntfs2btrfs-gitAUR 轉換NTFS分區。 卸載目標文件系統並運行轉換，並指定確切的壓縮和校驗和類型：

    # ntfs2btrfs -c zstd -h crc32c /dev/partition

如果轉換後一切正常，你可以刪除原本用於恢復原始文件系統的 `image/ntfs.img` 。

#### 轉換後

警告：只有在確認不會恢復到原始文件系統後，才執行這些步驟，因為它們會使得恢復變得不可能，即使你保留了恢復文件。

可以在將現有文件系統轉換為 Btrfs 後採取一些步驟使文件數據更連續。

    # btrfs filesystem defrag -v -r -f -t 32M /mnt/filesystem

#Balance 使 Btrfs 元數據更加緊湊

### 損壞恢復

警告：`btrfs check` 工具有一些已知問題，參見 #檢查 Btrfs 文件系統 小節。

btrfs-check 不能在一個已掛載的文件系統上工作。為了能夠在不從 Live USB 啟動的情況下使用 btrfs-check，需要將其添加到初始內存檔：

    /etc/mkinitcpio.conf

    BINARIES=(btrfs)

然後重新生成 initramfs。

之後如果啟動時出現問題，則可以使用該實用程序進行修復。

注意：如果 fsck 進程必須使空間緩存 (和/或其他緩存？) 無效 (invalidate cache)，那麼隨後的引導會掛起一段時間，這是正常的（進程可能會給出關於 btrfs-transaction 掛起的控制台消息）。系統應該在一段時間後從中恢復正常。

查閱 btrfs-check(8) 以獲取更多信息。

### 引導進入快照

要引導進入快照，因為快照可以像子卷那樣被掛載，所以請像掛載子卷為根分區那樣進行同樣的流程 (已交代於#掛載子卷為根掛載點的一段中)。

- 如果使用 GRUB，則可以在 grub-btrfs包 或 grub-btrfs-gitAUR 的幫助下，在重新生成配置文件時使用 Btrfs 快照自動填充啟動菜單。

- 如果使用 rEFInd，則可以在 refind-btrfsAUR 的幫助下，啟用 `refind-btrfs.service`後，在重新生成配置文件時使用 Btrfs 快照自動填充啟動菜單。

- 如果使用 Limine（英語：Limine），可安裝 limine-snapper-syncAUR。該工具在啟用 `limine-snapper-sync.service` 後，每當 Snapper 列表變更時，將自動在啟動菜單中生成快照條目。詳情參見 Lamine#Btrfs 的 Snapper 快照集成（英語：Limine#Snapper snapshot integration for Btrfs）。

### 搭配 systemd-nspawn 使用 Btrfs 子卷

可查閱 systemd-nspawn#使用Btrfs子卷作為容器的根和 systemd-nspawn#在 systemd-nspawn 中運行 docker 等文章。

### 減少訪問時間元數據的更新

由於Btrfs的寫時複製性質，訪問文件就能夠觸發元數據的寫時複製。減少訪問時間的更新頻率可能會消除這種不希望的硬碟使用並提高性能。參見Fstab#atime 參數

### 增量備份到外置設備

下列包利用 `btrfs send` 和 `btrfs receive` 將備份增量發送到外置設備上。 參考它們的文檔來查看實現，功能和需求的不同。

- btrbk — Btrfs子卷的快照和遠程備份工具

  https://github.com/digint/btrbk || btrbk包

- snap-sync — 使用Snapper快照並備份到外置設備或遠程機器

  https://github.com/wesbarnett/snap-sync || snap-sync包

下列工具運行備份snapper快照到非Btrfs文件系統。

- snapborg — 一個類似borgmatic的工具，將snapper快照與borg包整合起來

  https://github.com/enzingerm/snapborg || snapborgAUR

### 自動快照

要管理並自動創建快照，你可以使用像Snapper，Timeshift或Yabsnap這樣的快照管理器。

### 自動通知

桌面通知能幫助您及時察覺嚴重的 Btrfs 問題，相較於完全不提供通知，能提供更好的問題感知。

btrfs-desktop-notificationAUR 為以下事件提供桌面通知：

- 啟動進入任何只讀快照或系統時
- dmesg 日誌中出現 Btrfs 警告、錯誤或致命消息

更多信息及配置方法，請參見 https://gitlab.com/Zesko/btrfs-desktop-notification .

### 空間緩存v1正在被棄用

如果你的 Btrfs 文件系統是用舊的默認設置創建的，你可能會在你的系統日誌中看到類似的警告:

    BTRFS warning (device sdb4): space cache v1 is being deprecated and will be removed in a future release, please use -o space_cache=v2

將 Btrfs 空間緩存從舊版 v1 格式轉換為新版 v2 格式並解決此警告. 你可以修改分區掛載選項，在 fstab 中包含 `space_cache=v2` 或者手動進行轉換：

    # umount /dev/partition
    # mount /dev/partition -o rw,space_cache=v2 /mnt
    # umount /mnt

注意：在此轉換後，Btrfs會在文件系統上設置一個compat-ro功能標誌。因此，該文件系統可能無法再被非常舊的Btrfs內核實現掛載。

## 疑難解答

請查閱 Btrfs 疑難解答和Btrfs 常見問答集（英文）以獲得排除一般問題的信息。

### 啟動緩慢

有時，大於4TB的Btrfs卷需要較長時間才能掛載，從而導致系統啟動變慢。 將群組樹更改為塊組樹有助於解決該問題：

    # btrfstune --convert-to-block-group-tree /dev/device

### GRUB

#### 分區偏移

注意：當您試圖將 `core.img` 嵌入到已分區磁碟上時，可能會發生偏移問題。這意味著可以將 GRUB 的 `corg.img` 直接嵌入到無分區磁碟 (例如 `/dev/sdX`) 上的 Btrfs 存儲池中。

GRUB 可以引導啟動 Btrfs 分區，但是因為模塊可能會比其它文件系統大，`grub-install` 生成的 `core.img` 文件超過了 MBR 與第一個分區之間的空間大小 (63 扇區/31.5KiB)。最新版的 `fdisk` 和 `gdisk` 等磁碟工具會通過第一個分區前空出 1-2MiB 的空間來避免此問題。

#### 根丟失

本文或本章節的事實準確性存在爭議。

原因： Suggests editing a non-configuration file manually.（在 Talk:Btrfs#Should not suggest to edit files in /usr/share 中討論）

當從一個RAID配置的系統中啟動用戶可能會遇到錯誤：`error no such device: root`。編輯`/usr/share/grub/grub-mkconfig_lib`，移除行`echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"`中的兩個引號。重新生成grub的配置文件，後系統應該能夠正常啟動。

警告：不建議覆蓋軟體包提供的文件，因其會在下次更新時被覆蓋。

### 掛載超時

有時（尤其在大型 RAID1 陣列上）系統啟動時會出現掛載超時的現象，並帶有如下日誌信息：

    Jan 25 18:05:12 host systemd[1]: storage.mount: Mounting timed out. Terminating.
    Jan 25 18:05:46 host systemd[1]: storage.mount: Mount process exited, code=killed, status=15/TERM
    Jan 25 18:05:46 host systemd[1]: storage.mount: Failed with result 'timeout'.
    Jan 25 18:05:46 host systemd[1]: Failed to mount /data.
    Jan 25 18:05:46 host systemd[1]: Startup finished in 32.943s (firmware) + 3.097s (loader) + 7.247s (kernel)>
    Jan 25 18:05:46 host kernel: BTRFS error (device sda): open_ctree failed

這可以通過 fstab 中特定的 systemd 掛載選項 `x-systemd.mount-timeout` 提供系統以更長的超時時間來輕鬆解決。例如：

     UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  /data  btrfs  rw,relatime,x-systemd.mount-timeout=5min  0 0

### 出現 BTRFS: open_ctree failed 錯誤

本文或本章節的事實準確性存在爭議。

原因： 內容過時。自從systemd和udev都使用systemd-udevd後，用systemd替換udev鉤子沒有任何意義。（在 Talk:Btrfs 中討論）

截至 2014 年 11 月，一個似乎存在於 systemd 或 mkinitcpio 中的 Bug 可能會導致在 `mkinitcpio.conf` 中使用 `btrfs` 鉤子（hook）的用戶在啟動多設備文件系統的 Btrfs 卷時遇到以下錯誤：

    BTRFS: open_ctree failed
    mount: wrong fs type, bad option, bad superblock on /dev/sdb2, missing codepage or helper program, or other error

    In some cases useful info is found in syslog - try dmesg|tail or so.

    You are now being dropped into an emergency shell.

一種解決辦法是，在`/etc/mkinitcpio.conf`中，將 `HOOKS` 中的 `btrfs` 移入 `MODULES` 中，然後重新生成 initramfs 並重新啟動。

另外，如果在掛載 RAID 卷組缺少某個卷時，也有可能會發生這個錯誤。這種情況下，需要把 `degraded` 加入到 `/etc/fstab` 中；如果根目錄在卷組上，需要同時加入內核參數 `rootflags=degraded`。

接上文，截至 2016 年 8 月，針對這一問題，一個可能的解決方案是在 `/etc/fstab` 中僅靠單個硬碟來掛載陣列，然後讓 Btrfs 自動發現並追加其它硬碟。UUID 和 LABEL 等基於組的標識符似乎是導致出現錯誤的原因。比如說，由「disk1」（磁碟 1） 和「disk2」（磁碟 2）組成的雙設備 RAID1 陣列會被分配到一個 UUID。但是請在 `/etc/fstab` 中只使用 `/dev/mapper/disk1` 來指定磁碟陣列，而不要使用 UUID。更多解釋，參見這個博客文章。

另一個可能的解決方法是在 mkinitcpio.conf 中移除 `udev` 鉤子並替換為 `systemd` 鉤子。此時 `btrfs` 不應出現在 `HOOKS` 或 `MODULES` 列表中。

請查閱原論壇討論和 FS#42884 獲得更多的討論內容和信息。

### 檢查 Btrfs 文件系統

本文或本節內容已經過時。

原因： "大開發階段"狀態已經過時。 (在Talk:Btrfs討論)
警告：Btrfs（特別是 `btrfs check` 命令工具）仍處在大開發階段，強烈建議在加上 `--repair` 參數運行 `btrfs check` 前先做一個備份，並提前查閱 btrfs-check(8)。

btrfs-check(8) 可以檢查並修復一個未掛載的 Btrfs 文件系統。但是由於它尚未開發完成，它並不能修復某些錯誤（即使這些錯誤沒有導致文件系統無法掛載）。

### 持續的硬碟活動

自內核版本6.2開始， mount(8) 默認啟用 `discard=async` 選項。 這個設置被報告會造成硬碟的持續活動（甚至是待機狀態下），因為丟棄隊列填充的速度快於其處理速度。這會造成電源使用增加，特別是NVMe設備。

到了內核版本6.3後，問題的解決辦法是將`iops_limit`默認值從100改為1000。在舊版內核上，你可以手動設置到一個需要的值，例如：

    # echo 1000 > /sys/fs/btrfs/uuid/discard/iops_limit

其中`uuid`是btrfs文件系統的UUID。限制值`1000`需要通過實驗進行調整。

要在啟動時設置該參數，可能要用到Systemd#systemd-tmpfiles - 臨時文件，例如創建下列文件：

    /etc/tmpfiles.d/btrfs-discard.conf

    w /sys/fs/btrfs/uuid/discard/iops_limit - - - - 1000

或者在fstab中使用`nodiscard`掛載選項禁用異步丟棄功能，使用定期TRIM來替代。

### Device total_bytes should be at most X but found Y

若驅動器從其他計算機遷移或設備順序變更，且報告的大小差異極小（至多幾MB），可能是啟用了 HPA（主機保護區域）。

可使用 hdparm包 驗證 HPA 是否啟用：

    # hdparm -N 设备

輸出將顯示兩個數值：可見扇區數與實際扇區數。若兩者不同則表明HPA已啟用。

若主板強制設置此功能且固件未提供關閉選項，唯一解決方案是收縮受影響文件系統。此操作最易在原始計算機或未應用HPA的機器上執行。

### 設備空間不足

博客文章《解決Btrfs文件系統空間不足問題》建議並解釋了以下檢查步驟：

1. 立即清理空間（刪除歷史快照）
2. 文件系統是否真滿？元數據和/或數據塊分布不均（運行 `btrfs balance`）
3. 文件系統是否真滿？數據塊分布不均
4. 文件系統是否真滿？元數據分布不均
5. 因空間不足無法執行平衡操作（運行 `btrfs balance` 前，先用 `btrfs device add` 臨時添加設備如U盤或環回設備）

另可參閱 btrfs 元數據滿了怎麼辦 - 依雲's Blog。

有關 ENOSPC（「磁碟空間不足」）的最新處理指南，請參閱 ENOSPC - No available disk space | Forza's Ramblings。

## 另請參閱

- 官方網站
  - Btrfs 文檔
  - 已歸檔的 Btrfs 百科
- 性能相關
  - Btrfs on raw disks?
  - Varying leafsize and nodesize in Btrfs
  - Btrfs support for efficient SSD operation (data blocks alignment)
  - Is Btrfs optimized for SSDs?
  - Lzo vs. zLib
- 雜項
  - Funtoo:BTRFS Fun
  - Avi Miller presenting Btrfs at SCALE 10x, January 2012.
  - Summary of Chris Mason's talk from LFCS 2012
  - Btrfs: stop providing a bmap operation to avoid swapfile corruptions 2009-01-21
  - Doing Fast Incremental Backups With Btrfs Send and Receive

1. ↑ bees 的 issue 中有討論過，具體連結以後再補。

分類：​

- 文件系統
- 使用「模板:風格」標記的頁面或章節
- 使用「模板:過時」標記的頁面或章節

隱藏分類：​

- 使用「模板:準確性」標記的頁面或章節

Btrfs
新增話題