跳至內容

Btrfs

出自 Arch Linux 中文维基

譯自 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 文件系統中,元數據的默認節點大小為 16 KiB,而數據的默認扇區大小等於系統頁大小(自動檢測)。如需為元數據指定更大的節點大小(必須是扇區大小的整數倍且為 2 的整數次冪,最大允許 64 KiB),可通過 -n 選項設置節點大小(nodesize),如下例使用 32 KiB 的節點大小:

# mkfs.btrfs -L 自定义标签 -n 32k /dev/分区名
注意:根據 mkfs.btrfs(8) § OPTIONS 手冊頁內容:「較小的節點大小會導致碎片化,但 B 樹變得更高,從而能夠減少鎖競爭。較大的節點大小則能使數據更加緊湊並降低碎片化程度,但在更新元數據塊時內存操作開銷更大。」

多設備文件系統

[編輯 | 編輯原始碼]
警告:

可以為多個設備創建一個 Btrfs 文件系統。Btrfs 支持的 RAID 級別包括 RAID 0、RAID 1、RAID 10、RAID 5 和 RAID 6(詳情參閱下文 #profile)。Btrfs 的 RAID1 profile 僅保存 2 個副本,內核 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 中加入 udevsystemdbtrfs 鉤子之一才能使用多設備 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 中的 RAID1RAID1C3RAID1C4)結合使用時,斷電或其他導致損壞的原因可能會造成副本間的數據不同步。

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

注意:根據 btrfs(5) § MOUNT OPTIONS: 「在單個文件系統中,無法讓某些子卷使用 nodatacow 參數掛載,而其他的使用 datacow 參數掛載。第一個被掛載子卷的掛載參數將會應用於其他所有子卷。」

要禁用空文件或目錄中新文件(同上,不會影響其中已存在的寫時複製文件)的寫時複製特性,請使用下面的命令:

$ chattr +C 目录或文件路径
注意:
提示:為目錄中已存在的所有文件禁用寫時複製可以使用下面的方法:
$ 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 時),壓縮可以提升性能,但在其他場景中(如多線程或高 CPU 占用並涉及大量文件讀寫的任務),性能則會明顯下降。通常採用壓縮算法越快(zstdlzo)性能越好,一些基準測試提供了詳細的性能對比數據。

壓縮類型

[編輯 | 編輯原始碼]

Btrfs 支持的壓縮算法有 zlib(即 zlib 庫提供的 DEFLATE 壓縮算法)、lzo(即 LZO)和 zstd(即 zstd 實現的 Zstandard 壓縮算法)。其中 lzo 無壓縮級別,而 zlibzstd 可調整壓縮級別(zlib:1~9;zstd:-15~-1、1~15,需為整數),級別越高壓縮效果越好而所需時間越長。改變壓縮級別將直接影響 CPU 和 I/O 吞吐,因此,建議在變更前後分別執行基準測試以驗證優化效果。關於壓縮類型的更多信息,可參閱 btrfs(5) § COMPRESSION

警告:如果使用 zstd 算法(尤其是 -15~-1 級別),使用較舊的內核或 btrfs-progs 的系統可能不能讀取或修復您的文件系統。

啟用壓縮

[編輯 | 編輯原始碼]
為文件系統啟用
[編輯 | 編輯原始碼]

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

注意:
  • 壓縮掛載選項會在同一文件系統的所有掛載點(包括不同子卷與綁定掛載)之間共享 [6]
  • 若文件的一次寫入無法壓縮,此後寫入均不會進行壓縮。

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

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

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

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

提示:在新的 Btrfs 上安裝 Arch Linux 時,如果需要將其壓縮後存儲,需要在系統安裝前就使用 compress 選項掛載,例如:mount -o compress=zstd /dev/sdxY /mnt/,並注意在其 fstab 中為根目錄文件系統指定相同的 compress 掛載選項。
為現有文件啟用
[編輯 | 編輯原始碼]

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

# btrfs -v filesystem defragment -r -czstd -L1 /
警告:碎片整理會解除 #寫時複製(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 subvolume create 子卷父目录/子卷名

例如,在 /mnt 所在子卷下創建子卷 @sub(路徑為 /mnt/@sub):

# btrfs subvolume create /mnt/@sub
注意:
  • 使用 -p--parents)選項可以自動創建不存在的父目錄。
  • Btrfs 中子卷名可以是任何有效的目錄名,以 @ 符號開頭只是一個常見的命名約定。

列出子卷

[編輯 | 編輯原始碼]

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

# btrfs subvolume list -t 路径

-t 選項會觸發更易讀的表格視圖。

刪除子卷

[編輯 | 編輯原始碼]

刪除子卷:

# btrfs subvolume delete 子卷路径

如果子卷包含其他子卷,需要添加 -R--recursive)選項遞歸刪除包含的所有子卷。子卷也可以當作常規目錄刪除(使用 rm -rrmdir)。

警告:確保在刪除子卷之前未掛載該子卷。刪除已掛載的子卷可能導致文件系統不一致。

掛載子卷

[編輯 | 編輯原始碼]

將需掛載的子卷設置為默認子卷或使用 subvol=子卷路徑(相對於頂層子卷)subvolid=子卷ID 標誌掛載文件系統,可以將子卷像文件系統分區一樣掛載。例如,可以將一個名為 subvol_root 的子卷掛載為 /。通過在頂層子卷下創建各種子卷,然後掛載到適當的掛載點,模擬傳統的文件系統分區。因為子卷 ID 在恢復 #快照時可能會改變,建議使用 subvol 參數掛載子卷。

提示:
  • 子卷 ID 可通過 #列出子卷顯示。
  • 不使用默認做法(將頂層子卷作為 /)可以簡化子卷布局的更改。因此,考慮創建一個子卷掛載為 /
注意:
  • 如果要將子卷掛載為 /,需要在 rootflags 內核參數中指定掛載子卷的選項(一些引導加載程序可以自動添加,例如 GRUBgrub-mkconfig 命令),並編輯 /etc/fstab。或者,可以 #更改默認子卷
  • 譯自 btrfs(5) § MOUNT OPTIONS:「大多數掛載選項應用於整個文件系統,只有第一個掛載的子卷的選項才會生效。這是由於實現缺失,將來可能會改變。這意味著(例如)你無法使用掛載選項為每個子卷單獨設置 nodatacownodatasumcompress。這最終應該會被修復,但事實證明在 Linux VFS 框架內正確實現是困難的。」

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

請參閱 Snapper#建議的文件系統布局Btrfs SysadminGuide#Managing SnapshotsSysadminGuide#Layout,了解使用子卷的示例文件系統布局。

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

更改默認子卷

[編輯 | 編輯原始碼]

如果沒有提供 subvolsubvolid 選項,將掛載默認子卷。要將子卷設置為所在文件系統的默認子卷,執行:

# btrfs subvolume set-default 子卷路径

或者使用:

# btrfs subvolume set-default 子卷ID 路径

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

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

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

注意:GRUBgrub-mkconfig 腳本遵守 Btrfs 的默認子卷設置⸺如果 / 是頂層子卷,始終不會指定 subvol=/subvolid=5 掛載選項,可能導致無法啟動;如果 / 非頂層子卷,始終會指定相應的 subvol 選項,導致無法僅通過設置默認子卷回退(bug 報告)。目前可以通過手動修改 grub.cfgrootflags 內核參數解決(參見 #掛載子卷),或者使用工具自動在 GRUB 中為快照創建啟動項(參見 #引導進入快照)。另外,如果 grub.cfg 的實際位置發生改變,例如包含 /boot 的子卷改變,需要再次運行 grub-install。詳見這個論壇帖子

配額

[編輯 | 編輯原始碼]

磁碟配額的概念在 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)歸屬於首次分配它的子卷,而該子卷已完全刪除但區段仍被其他子卷引用。

根據需求,可以添加一些顯示選項(到 show 之後)。常用的選項有:

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

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

配額重掃描
[編輯 | 編輯原始碼]

配額重掃描(quota rescan)會讀取文件系統中所有區段(extent)的元數據,據其更新各配額組的統計值。

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

目前實現中唯一例外是分配/解除分配的子配額組的總引用空間等於獨占引用空間(即所有數據都為獨占)時,僅在父配額組的總引用空間與獨占引用空間同時加上/減去其引用空間,從而避免配額重掃描。

自內核 4.19 版本起,手動 #分配/解除分配子配額組時會自動觸發配額重掃描(除了以上例外情況)。但出於其開銷較大、同時只能進行一次且以這種方式無法等待重掃描結束後返回等原因,可以添加 --no-rescan 選項(到 assign/remove 之後)避免自動觸發,在之後手動觸發。

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

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

# btrfs quota rescan 路径

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

簡單配額

[編輯 | 編輯原始碼]

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

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

簡單配額需要在文件系統級別啟用,只需要在啟用配額組的命令中添加 -s--simple)選項(到 enable 之後)。注意若已開啟配額組,需要先禁用配額組再啟用簡單配額,否則不會生效 [12]。由於其簡單的計算方法,簡單配額模式下不需要(也不能)進行 #配額重掃描。除了這兩點外,簡單配額的操作方式與配額組完全相同,但顯示與限制使用的所謂「總引用空間」和「獨占引用空間」都是通過上文所述方法(將所有區段歸屬於首次分配它的子卷)計算得到的值。由於簡單配額需要記錄首次分配區段的子卷,因此僅對啟用後寫入的區段生效,若在非空文件系統中啟用簡單配額,剛啟用時統計值會是 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 無需根權限快速檢查已分配空間及其使用情況:

$ btrfs filesystem df /
注意:對於 #多設備文件系統btrfs filesystem usageRAID5RAID6 #profile 與其它 profile 共存於一文件系統(例如,元數據使用 DUP 而數據使用 RAID5)時,以上兩種方式顯示出的空間使用情況不準確 [14]

更多信息可參閱 [15]

du(1)ncdu(1) 之類分析文件系統或其部分區域的空間使用情況的工具也不能準確計算剩餘空間,因其不考慮 #寫時複製(CoW)特性和透明 #壓縮。考慮改用 btduAURcompsize 等可識別 Btrfs 特性的工具。

碎片整理

[編輯 | 編輯原始碼]

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

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

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

警告:碎片整理會解除 #寫時複製(CoW)數據(包括通過 cp 複製的文件、#快照#去重數據等)之間的 reflink,產生獨立的文件,可能顯著增加空間使用量 [16]

手動

[編輯 | 編輯原始碼]

使用 btrfs filesystem defragment 命令手動進行碎片整理,例如碎片整理根目錄下的文件(不進入子卷、掛載點及連結的目錄):

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

自動

[編輯 | 編輯原始碼]

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

檢修

[編輯 | 編輯原始碼]

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

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

手動

[編輯 | 編輯原始碼]

使用以下命令在後台啟動檢修任務(此處「設備」指 Linux 塊設備):

# btrfs scrub start 路径设备

如果指定路徑,則檢修路徑所在的文件系統;如果指定設備,則檢修該設備。

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

檢查該任務的運行狀態:

# 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 將會通過分配器再次傳遞文件系統中的所有數據。它主要用於在添加或刪除設備時跨設備重新平衡文件系統中的數據。如果設備出現故障,餘額將為冗餘 RAID 級別重新生成缺失的副本。"[17]。參閱上游的 FAQ.

在單設備文件系統上,數據平衡對於(臨時)減少分配但未使用(元)數據塊的數量也是有用的。有時候這對於解決 "filesystem full" 故障來說也是必須的。

# 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#交換文件

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

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

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

快照

[編輯 | 編輯原始碼]

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

要創建一個快照:

# 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 分區去重的工具包括 duperemovebees。也許你還希望基於文件的級別對數據進行重複數據刪除,比如 rmlint-gitrdfindjdupesAUR 或者 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 能占用整個存儲設備,使用子卷模擬分區表來替代 MBRGPT 分區表。雖然無分區磁碟不需要使用其它方法創建分區,然後在一個分區上創建 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小時。

損壞恢復

[編輯 | 編輯原始碼]
警告: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-btrfsgrub-btrfs-gitAUR 的幫助下,在重新生成配置文件時使用 Btrfs 快照自動填充啟動菜單。
  • 如果使用 rEFInd,則可以在 refind-btrfsAUR 的幫助下,啟用 refind-btrfs.service後,在重新生成配置文件時使用 Btrfs 快照自動填充啟動菜單。

搭配 systemd-nspawn 使用 Btrfs 子卷

[編輯 | 編輯原始碼]

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

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

[編輯 | 編輯原始碼]

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

增量備份到外置設備

[編輯 | 編輯原始碼]

下列包利用 btrfs sendbtrfs 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

自動快照

[編輯 | 編輯原始碼]

要管理並自動創建快照,你可以使用像SnapperTimeshiftYabsnap這樣的快照管理器。

自動通知

[編輯 | 編輯原始碼]

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

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

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

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

疑難解答

[編輯 | 編輯原始碼]

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

分區偏移

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

GRUB 可以引導啟動 Btrfs 分區,但是因為模塊可能會比其它文件系統大,grub-install 生成的 core.img 文件超過了 MBR 與第一個分區之間的空間大小 (63 扇區/31.5KiB)。最新版的 fdiskgdisk 等磁碟工具會通過第一個分區前空出 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 月,一個似乎存在於 systemdmkinitcpio 中的 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 不應出現在 HOOKSMODULES 列表中。

請查閱原論壇討論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

另請參閱

[編輯 | 編輯原始碼]