Btrfs

来自 ArchWiki

来自 Btrfs 文档

Btrfs 是 Linux 的现代写入时复制 (COW) 文件系统,旨在实现高级功能,同时专注于容错、修复和易于管理。
注意: 与其他一些文件系统一样,Btrfs 也在持续开发中。这意味着某些特定功能可能尚未准备好用于日常使用。要查看您的用例是否可能受到影响,请查看 Btrfs 文档的 Status 部分和本文的 #已知问题 部分。

准备工作

对于用户空间实用程序,安装 btrfs-progs 软件包,这是基本操作所必需的。

如果您需要从 Btrfs 文件系统启动(即,您的内核和 initramfs 位于 Btrfs 分区上),请检查您的引导加载程序是否支持 Btrfs。

文件系统创建

以下说明如何创建新的 Btrfs 文件系统。要将 Ext3/4 分区转换为 Btrfs,请参阅 #Ext3/4 到 Btrfs 转换。要使用无分区设置,请参阅 #无分区 Btrfs 磁盘

有关更多信息,请参阅 mkfs.btrfs(8)

单设备文件系统

要在分区 /dev/partition 上创建 Btrfs 文件系统

# mkfs.btrfs -L mylabel /dev/partition

Btrfs 元数据的默认节点大小为 16 KiB,而数据的默认扇区大小等于页面大小并自动检测。要为元数据使用更大的节点大小(必须是扇区大小的倍数,最大允许 64 KiB),请通过 -n 开关指定 nodesize 的值,如本示例所示,使用 32 KiB 块

# mkfs.btrfs -L mylabel -n 32k /dev/partition
注意: 根据 mkfs.btrfs(8) § OPTIONS,“[a] 较小的节点大小会增加碎片,但会导致更高的 b 树,从而降低锁定争用。较高的节点大小可以更好地打包并减少碎片,但代价是在更新元数据块时需要更昂贵的内存操作”。

多设备文件系统

警告

可以使用多个设备创建 RAID。支持的 RAID 级别包括 RAID 0、RAID 1、RAID 10、RAID 5 和 RAID 6。从内核 5.5 开始,RAID1c3 和 RAID1c4 用于 RAID 1 级别的 3 份和 4 份副本。可以使用 -d-m 选项分别配置数据和元数据的 RAID 级别。默认情况下,数据有一份副本 (single),元数据是镜像的 (raid1)。这类似于创建 JBOD 配置,其中磁盘被视为一个文件系统,但文件不会重复。有关如何创建 Btrfs RAID 卷的更多信息,请参阅 Using Btrfs with Multiple Devices

# mkfs.btrfs -d single -m raid1 /dev/part1 /dev/part2 ...

您必须在 /etc/mkinitcpio.conf 中包含 udev 钩子、systemd 钩子或 btrfs 钩子,才能在池中使用多个 Btrfs 设备。有关更多信息,请参阅 Mkinitcpio#常用钩子 文章。

文件系统创建后,建议运行以下命令扫描多设备 Btrfs 文件系统并注册它们,从而允许通过仅指定一个成员来挂载多设备文件系统

# btrfs device scan
注意
  • 稍后可以向多设备文件系统添加设备。有关更多信息,请参阅 Btrfs wiki 文章
  • 设备的大小可以不同。但是,如果 RAID 配置中的一个驱动器比其他驱动器大,则不会使用此额外空间。
  • 某些引导加载程序(如 Syslinux)不支持多设备文件系统。
  • Btrfs 不会自动从最快的设备读取数据,因此混合使用不同类型的磁盘会导致性能不一致。有关详细信息,请参阅 [1]

有关特定于多设备 Btrfs 文件系统的维护建议,请参阅 #RAID

配置文件

Btrfs 使用配置文件的概念来配置镜像、奇偶校验和条带化。在标准 RAID 术语中,这称为RAID 级别。同一 Btrfs 文件系统的元数据(mkfs.btrfs(8)-m 选项)和数据(mkfs.btrfs(8)-d 选项)的配置文件可能不同。

一些值得注意的配置文件

single
无镜像、无条带化、无奇偶校验,允许将多个设备映射到单个文件系统,在 mdadm 术语中称为 LINEAR
raid0
无镜像、条带化、无奇偶校验,允许设备之间的并行访问,但不限于像传统 mdadm RAID 那样的同等大小的设备。
raid1
镜像、无条带化、无奇偶校验,允许从一个驱动器故障中恢复。

配置文件系统

写入时复制 (CoW)

默认情况下,Btrfs 始终对所有文件使用 写入时复制。写入不会覆盖原始位置的数据;相反,块的修改副本会被写入新位置,并且元数据会更新以指向新位置。有关实现细节以及优缺点,请参阅 Btrfs Sysadmin Guide 部分

禁用 CoW

警告: 在 Btrfs 中禁用 CoW 也会禁用校验和。Btrfs 将无法检测到损坏的 nodatacow 文件。当与 RAID 1 结合使用时,电源中断或其他损坏源可能会导致数据不同步。

要在已挂载的子卷中禁用新创建文件的写入时复制,请使用 nodatacow 挂载选项。这只会影响新创建的文件。写入时复制仍然会发生在现有文件上。nodatacow 选项还会禁用压缩。有关详细信息,请参阅 btrfs(5)

注意: 来自 btrfs(5) § MOUNT OPTIONS:“在单个文件系统中,无法将某些子卷挂载为 nodatacow,而将另一些子卷挂载为 datacow。第一个挂载的子卷的挂载选项适用于任何其他子卷。”

要禁用单个文件/目录的写入时复制,请执行

$ chattr +C /dir/file
注意: 来自 Btrfs 文档: 文件属性:“当在目录上设置时,所有新创建的文件都将继承此属性。由于实现限制,此标志只能在空文件上设置/取消设置。”
提示: 根据上述说明,您可以使用以下技巧在目录中的现有文件上禁用写入时复制
$ 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=nevermvcp 将不起作用。
对快照的影响

如果文件禁用了写入时复制 (NOCOW) 并且已创建快照,则快照后对文件块的第一次写入将是 COW 操作,因为快照会锁定旧的文件块。但是,该文件将保留 NOCOW 属性,并且对同一文件块的任何后续写入都将是就地写入,直到下一个快照。

频繁快照可能会降低 NOCOW 的有效性,因为第一次写入仍然需要 COW。为了完全避免此类文件的写入时复制,请将它们放在单独的子卷中,并且不要对该子卷进行快照。

压缩

Btrfs 支持透明和自动压缩。这可以减小文件大小,并通过减少写入放大来显着延长基于闪存的介质的寿命。请参阅 Fedora:Changes/BtrfsByDefault#Compression[2][3]。在某些情况下(例如,单线程和大量文件 I/O),它还可以提高性能,而在其他情况下(例如,多线程和/或 CPU 密集型任务以及大量文件 I/O),显然会损害性能。通常,使用最快的压缩算法 zstdlzo 可以获得更好的性能,并且一些 基准测试 提供了详细的比较。

LZO 具有固定的压缩级别,而 zlib 和 zstd 具有从 1(低压缩)到 9 (zlib) 或 15 (zstd) 的级别范围;请参阅 btrfs(5) § COMPRESSION。更改级别会以不同的方式影响 CPU 和 I/O 吞吐量,因此应在更改前后进行检查/基准测试。

compress=alg[:level] 挂载选项允许自动考虑每个文件是否进行压缩,其中 alg 可以是 zliblzozstdno(不压缩)。使用此选项,Btrfs 将检查压缩数据的第一部分是否会缩小它。如果会缩小,则对该文件的整个写入将被压缩。如果不会缩小,则不会压缩任何内容。使用此选项,如果写入的第一部分没有缩小,则即使数据的其余部分会大幅缩小,也不会对写入应用压缩。[4] 这样做是为了防止磁盘等待开始写入,直到要写入的所有数据都完全提供给 Btrfs 并压缩。

此条目或章节需要扩充。

原因: 缺少对以下段落中提到的“经验测试”的引用。(在 Talk:Btrfs 中讨论)

可以改用 compress-force=alg[:level] 挂载选项,这使得 Btrfs 跳过检查压缩是否会缩小第一部分,并为每个文件启用自动压缩尝试。在最坏的情况下,这可能会导致(稍微)更多的 CPU 使用率,但没有任何目的。但是,对多个混合使用系统的经验测试表明,使用 compress-force=zstd 比仅使用 compress=zstd(也具有 10% 的磁盘压缩率)可以显着提高约 10% 的磁盘压缩率。但是,请记住,强制压缩违反了 官方 Btrfs 指南

只有在添加挂载选项后创建或修改的文件才会被压缩。

要将压缩应用于现有文件,请使用 btrfs filesystem defragment -calg 命令,其中 alg 可以是 zliblzozstd。例如,为了使用 zstd 重新压缩整个文件系统,请运行以下命令

# btrfs filesystem defragment -r -v -czstd /
警告: 对具有 COW 副本(快照副本或使用 cp 或 bcp 创建的副本)的文件进行碎片整理,再加上使用带有压缩算法的 -c 开关,可能会导致两个不相关的文件,从而有效地增加磁盘使用率。

要在将 Arch 安装到空的 Btrfs 分区时启用压缩,请在挂载文件系统时使用 compress 选项:mount -o compress=zstd /dev/sdxY /mnt/。在配置期间,将 compress=zstd 添加到 fstab 中根文件系统的挂载选项。

提示: 也可以在不使用 compress 挂载选项的情况下为每个文件启用压缩;为此,请对文件应用 chattr +c btrfs property set file compression alg。第一个命令使用从 ext2 文件系统继承的文件属性的旧接口,并且不够灵活,因此默认情况下设置 zlib 压缩。另一个命令使用给定的算法在文件上设置属性。(注意:尚未实现以这种方式设置级别。)当应用于目录时,它将导致新文件在创建时自动压缩。
警告
  • 如果您使用此选项,则使用旧内核或没有 zstd 支持的 btrfs-progs 的系统可能无法读取或修复您的文件系统。
  • GRUB 在 2.04 中引入了 zstd 支持。通过使用适用于您的 BIOS/UEFI 设置的适当选项运行 grub-install,确保您实际上已升级自那时起安装在 MBR/ESP 中的引导加载程序,因为这不是自动完成的。请参阅 FS#63235

查看压缩类型和比率

compsize 接受文件列表(或整个 Btrfs 文件系统),并测量使用的压缩类型和有效的压缩率。未压缩的大小可能与 du(1) 等其他程序给出的数字不匹配,因为每个区段都只计数一次,即使它被多次重新链接,并且即使它的一部分不再在任何地方使用但尚未进行垃圾回收。-x 选项使其保持在单个文件系统上,这在 compsize -x / 等情况下很有用,以避免它尝试查找非 Btrfs 子目录并导致整个运行失败。

子卷

“Btrfs 子卷不是块设备(也不能被视为块设备),相反,Btrfs 子卷可以被认为是 POSIX 文件命名空间。可以通过文件系统的顶层子卷访问此命名空间,也可以将其自身挂载。” [5]

每个 Btrfs 文件系统都有一个 ID 为 5 的顶层子卷。此子卷无法删除或替换为另一个子卷。顶层子卷在文件系统上的路径为 /,其他子卷嵌套在顶层子卷下方。但是,子卷可以在文件系统中移动,它们的路径可能会更改,而它们的 ID 不会更改。

默认情况下,挂载文件系统时会挂载顶层子卷。选项允许改为挂载特定的子卷

子卷的主要用例是 快照

有关更多详细信息,请参阅以下链接

创建子卷

要创建子卷,必须挂载 Btrfs 文件系统。子卷的名称使用最后一个参数设置。

# btrfs subvolume create /path/to/subvolume
注意: 您可以使用 --parents 自动创建父目录(如果它们不存在)。

列出子卷

要查看路径所属文件系统的所有子卷的列表

# btrfs subvolume list -t path

-t 触发更易读的表格视图。

删除子卷

要删除子卷

# btrfs subvolume delete /path/to/subvolume

如果子卷包含应删除的其他子卷,请添加 -R/--recursive 选项。或者,可以像常规目录一样删除子卷 (rm -r, rmdir)。

警告: 确保在删除子卷之前未挂载该子卷。删除已挂载的子卷可能会导致文件系统不一致。

挂载子卷

可以使用 subvol=/path/to/subvolumesubvolid=objectid 挂载标志像文件系统分区一样挂载子卷。例如,您可以创建一个名为 subvol_root 的子卷并将其挂载为 /。可以通过在文件系统的顶层下创建各种子卷,然后将它们挂载到适当的挂载点来模拟传统的文件系统分区。最好使用 subvol=/path/to/subvolume 而不是 subvolid 进行挂载,因为 subvolid 在还原 #快照 时可能会更改,从而需要更改挂载配置。

提示: 通过不使用顶层子卷 (ID=5) 作为 /(默认情况下是这样做的),可以更轻松地更改子卷布局。相反,请考虑创建一个子卷来存放您的实际数据并将其挂载为 /
注意: 来自 btrfs(5) § MOUNT OPTIONS:“大多数挂载选项都适用于整个文件系统,只有第一个要挂载的子卷的选项才会生效。这是由于缺乏实现,将来可能会更改。”

有关每个子卷可以使用哪些挂载选项,请参阅 Btrfs Wiki FAQ

有关使用子卷的文件系统布局示例,请参阅 Snapper#建议的文件系统布局Btrfs SysadminGuide#管理快照SysadminGuide#Layout

有关 Btrfs 特定的挂载选项的完整列表,请参阅 btrfs(5)

将子卷挂载为根目录

要将子卷用作根挂载点,请将其设置为默认子卷,或使用内核参数 rootflags=subvol=/path/to/subvolume 指定子卷。在 /etc/fstab 中编辑根挂载点,并指定挂载选项 subvol=。或者,可以使用其 id 指定子卷,rootflags=subvolid=objectid 作为内核参数,subvolid=objectid 作为 /etc/fstab 中的挂载选项。最好使用 subvol=/path/to/subvolume 而不是 subvolid 进行挂载,因为 subvolid 在还原 #快照 时可能会更改,从而需要更改挂载配置,否则系统将无法启动。

更改默认子卷

如果未提供 subvol= 挂载选项,则会挂载默认子卷。要更改默认子卷,请执行

# btrfs subvolume set-default subvolume-id /

其中 subvolume-id 可以通过列出找到。

注意: 在具有 GRUB 的系统上更改默认子卷后,您应再次运行 grub-install 以通知引导加载程序更改。请参阅此论坛帖子

使用 btrfs subvolume set-default 更改默认子卷将使文件系统的顶层不可访问,除非使用 subvol=/subvolid=5 挂载选项 [6]

配额

警告: Qgroup 尚不稳定,将配额与(过多)子卷快照结合使用可能会导致性能问题,例如在删除快照时。此外,还有更多已知问题

Btrfs 中的配额支持在子卷级别通过使用配额组或 qgroup 实现:默认情况下,每个子卷都分配了一个配额组,形式为 0/subvolume_id。但是,如果需要,可以使用任何数字创建配额组。

要使用 qgroups,您需要首先使用以下命令启用配额

# btrfs quota enable path

从此刻开始,新创建的子卷将受这些组控制。为了追溯性地为已存在的子卷启用它们,请正常启用配额,然后使用每个子卷的 subvolume_id 为每个子卷创建一个 qgroup(配额组)并重新扫描它们

# btrfs subvolume list path | cut -d' ' -f2 | xargs -I{} -n1 btrfs qgroup create 0/{} path
# btrfs quota rescan path

Btrfs 中的配额组形成树层次结构,其中 qgroup 附加到子卷。大小限制是按 qgroup 设置的,并且当树中包含给定子卷的任何限制达到时,该限制会生效。

配额组的限制可以应用于总数据使用量、未共享数据使用量、压缩数据使用量或两者。文件复制和文件删除都可能影响限制,因为如果原始卷的文件被删除并且仅剩一份副本,则另一个 qgroup 的未共享限制可能会更改。例如,新的快照与原始子卷共享几乎所有块,对任一子卷的新写入将朝着独占限制增加,删除一个卷中的公共数据会朝着另一个卷中的独占限制增加。

要对 qgroup 应用限制,请使用命令 btrfs qgroup limit。根据您的使用情况,可以使用总限制、未共享限制 (-e) 或压缩限制 (-c)。要显示文件系统中给定路径的使用情况和限制,请使用

# btrfs qgroup show -reF path

提交间隔

数据写入文件系统的分辨率由 Btrfs 本身和系统范围的设置决定。Btrfs 默认为 30 秒的检查点间隔,新数据在该间隔内提交到文件系统。可以通过在 /etc/fstab 中为 Btrfs 分区附加 commit 挂载选项来更改此设置。

LABEL=arch64 / btrfs defaults,compress=zstd,commit=120 0 0

系统范围的设置也会影响提交间隔。它们包括 /proc/sys/vm/* 下的文件,并且超出了本文的范围。有关它们的内核文档,请访问 https://docs.linuxkernel.org.cn/admin-guide/sysctl/vm.html

SSD TRIM

Btrfs 文件系统能够从支持 TRIM 命令的 SSD 驱动器中释放未使用的块。异步丢弃支持可通过挂载选项 discard=async 获得,并且自 linux 6.2 起默认启用。释放的区段不会立即丢弃,而是分组在一起,稍后由单独的工作线程进行 TRIM,从而改善提交延迟。

异步丢弃可以安全地与定期 TRIM [7] 一起使用。

关于启用和使用 TRIM 的更多信息,请参阅 固态硬盘#TRIM

用法

交换文件

注意: 不支持跨越多个设备的交换文件系统。有关所有限制,请参阅 btrfs(5) § SWAPFILE 支持

要正确初始化交换文件,首先创建一个非快照子卷来托管该文件,例如:

# btrfs subvolume create /swap
提示: 考虑直接在顶级子卷下创建子卷,例如 @swap。然后,确保将该子卷挂载/swap(或任何其他可访问的位置)。

创建交换文件

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

如果省略 --size,则默认使用 2GiB。

激活交换文件

# swapon /swap/swapfile

最后,编辑 fstab 配置文件以添加交换文件的条目

/etc/fstab
/swap/swapfile none swap defaults 0 0

有关更多信息,请参阅 fstab#用法

注意: 您也可以手动创建交换文件,方法是在整个子卷上设置 No_COW 属性(使用 chattr),然后按照 Swap#交换文件创建 中的步骤操作。有关替代方法,请参阅 btrfs(5) § SWAPFILE 支持

要将交换文件用于休眠,您可能还需要按照 休眠 中描述的步骤进行操作。

显示已用/可用空间

通用的 Linux 用户空间工具,如 df(1),将不准确地报告 Btrfs 分区上的可用空间。建议使用 btrfs filesystem usage 查询 Btrfs 分区。例如,要获得设备分配和使用统计的完整细分:

# btrfs filesystem usage /
注意: btrfs filesystem usage 命令目前无法在 RAID5/RAID6 RAID 级别下正常工作。

或者,btrfs filesystem df 允许快速检查已分配空间的使用情况,而无需以 root 身份运行

$ btrfs filesystem df /

有关更多信息,请参阅 [8]

相同的限制适用于分析文件系统某些子集空间使用情况的工具,例如 du(1)ncdu(1),因为它们没有考虑 reflinks、快照和压缩。相反,请参阅 btduAURcompsize 以获取 Btrfs 感知的替代方案。

碎片整理

Btrfs 支持通过挂载选项 autodefrag 进行在线碎片整理;请参阅 btrfs(5) § 挂载选项。要手动整理您的根目录,请使用:

# btrfs filesystem defragment -r /

在没有 -r 开关的情况下使用上述命令将仅导致包含目录的子卷所持有的元数据被碎片整理。这允许通过简单地指定路径来进行单个文件碎片整理。

警告: 对具有 COW 副本(快照副本或使用 cp 或 bcp 创建的副本)的文件进行碎片整理,再加上使用带有压缩算法的 -c 开关,可能会导致两个不相关的文件,从而有效地增加磁盘使用率。

RAID

Btrfs 为 #多设备文件系统 提供原生 “RAID”。使 Btrfs RAID 与 mdadm 区分开来的显著功能是自愈冗余阵列和在线平衡。有关更多信息,请参阅 Btrfs wiki 页面。Btrfs 系统管理员页面也有一个部分提供了更多技术背景。

警告: 奇偶校验 RAID (RAID 5/6) 代码中存在多个严重的数据丢失错误。请参阅 Btrfs Wiki 的 RAID5/6 页面linux-btrfs 邮件列表上的错误报告,以获取更详细的信息。2020 年 6 月,有人发布了 当前问题的全面列表有用的恢复指南

Scrub

此条目或章节需要扩充。

Btrfs Wiki 术语表指出,Btrfs scrub 是“[一种]在线文件系统检查工具。读取文件系统上的所有数据和元数据,并使用校验和和来自 RAID 存储的重复副本,以识别和修复任何损坏的数据。”

注意: 正在运行的 scrub 进程将阻止系统挂起,有关详细信息,请参阅 此线程
手动启动

要在包含 / 的文件系统上启动(后台)scrub:

# btrfs scrub start /

要检查正在运行的 scrub 的状态:

# btrfs scrub status /
使用服务或定时器启动

btrfs-progs 软件包带来了 btrfs-scrub@.timer 单元,用于每月 scrub 指定的挂载点。启用带有转义路径的定时器,例如 btrfs-scrub@-.timer 用于 /btrfs-scrub@home.timer 用于 /home。您可以使用 systemd-escape -p /path/to/mountpoint 来转义路径;有关详细信息,请参阅 systemd-escape(1)

您也可以通过启动 btrfs-scrub@.service (使用相同的编码路径)来运行 scrub。与 btrfs scrub (以 root 用户身份)相比,其优势在于 scrub 的结果将记录在 systemd 日志中。

在散热不足的大型 NVMe 驱动器上(例如在笔记本电脑中),scrub 可能会以足够快且足够长的时间读取驱动器,使其变得非常热。如果您正在使用 systemd 运行 scrub,则可以使用 drop-in 文件轻松地使用 systemd.resource-control(5) 中描述的 IOReadBandwidthMax 选项来限制 scrub 的速率。

Balance

“balance 再次通过分配器传递文件系统中的所有数据。它主要用于在添加或删除设备时重新平衡文件系统中跨设备的数据。如果设备发生故障,balance 将为冗余 RAID 级别重新生成丢失的副本。” [9] 请参阅 上游 FAQ 页面

在单设备文件系统上,balance 也可能有助于(临时)减少已分配但未使用的(元)数据块的数量。有时,这对于修复 “文件系统已满”问题是必需的。

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

快照

“快照只是一个子卷,它使用 Btrfs 的 COW 功能与其他一些子卷共享其数据(和元数据)。” 有关详细信息,请参阅 Btrfs Wiki SysadminGuide#快照

要创建快照:

# btrfs subvolume snapshot source [dest/]name

要创建只读快照,请添加 -r 标志。要创建只读快照的可写版本,只需创建其快照即可。

注意
  • 可以使用 btrfs property set -f -ts '/path/to/snapshot' ro false 将快照就地从只读转换为可写。但是,不建议这样做,因为它会导致问题,影响未来的任何增量发送/接收。制作新的可写快照可以防止此类问题。
  • 快照不是递归的。每个嵌套的子卷都将是快照中的一个空目录。

发送/接收

可以使用 send 命令将子卷发送到 stdout 或文件。当管道传输到 Btrfs receive 命令时,这通常最有用。例如,要将名为 /root_backup 的快照(可能是您之前为 / 制作的快照)发送到 /backup,您可以执行以下操作:

# btrfs send /root_backup | btrfs receive /backup

发送的快照必须是只读的。上述命令对于将子卷复制到外部设备(例如,上面挂载在 /backup 的 USB 磁盘)很有用。

将在接收端创建子卷。无需手动创建。

另一个示例,它创建:/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 的新只读快照,那么要仅将增量差异发送到 /backup,请执行:

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

现在,/backup 中将存在一个名为 root_backup_new 的新子卷。

有关如何将此用于增量备份以及用于自动化该过程的工具,请参阅 Btrfs Wiki 的增量备份页面#增量备份到外部驱动器

去重

通过写时复制,Btrfs 能够复制文件或整个子卷,而无需实际复制数据。但是,每当文件被更改时,都会创建一个新的实际副本。去重更进一步,通过主动识别共享公共序列的数据块,并将它们组合成具有相同写时复制语义的区段。

专用于去重 Btrfs 格式化分区的工具包括 duperemovebees。人们可能还希望仅在文件级别上去重数据,而不是使用例如 rmlint-gitAURrdfindjdupesAURdduper-gitAUR。有关这些程序可用功能和附加信息的概述,请查看 上游 Wiki 条目

调整大小

警告: 为避免数据丢失,请确保在开始任何调整大小的任务之前备份您的数据。

您可以将文件系统扩展到设备上可用的最大空间,或指定确切的大小。在尝试增加文件系统的大小之前,请确保增加设备或逻辑卷的大小。当为设备上的文件系统指定确切大小时(无论是增加还是减小),请确保新大小满足以下条件:

  • 新大小必须大于现有数据的大小;否则,会发生数据丢失。
  • 新大小必须等于或小于当前设备大小,因为文件系统大小不能超出可用空间。
注意: 如果您还计划减小容纳文件系统的逻辑卷的大小,请确保在尝试减小设备或逻辑卷的大小之前减小文件系统的大小。

要将文件系统大小扩展到设备的最大可用大小:

# btrfs filesystem resize max /

要将文件系统扩展到特定大小:

# btrfs filesystem resize size /

size 替换为所需的字节大小。您也可以在值上指定单位,例如 K(千字节)、M(兆字节)或 G(吉字节)。或者,您可以通过在值前加上加号 (+) 或减号 (-) 来指定相对于当前大小的增加或减少:

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

已知问题

在尝试之前,应了解一些限制。

加密

Btrfs 没有内置的加密支持,但这可能会在未来实现。用户可以在运行 mkfs.btrfs 之前加密分区,请参阅 dm-crypt/加密整个系统。另一种方法是 堆叠文件系统加密

btrfs check 问题

工具 btrfs check 存在已知问题,不应在未进一步阅读的情况下运行;请参阅 #btrfs check 部分。

技巧和窍门

无分区 Btrfs 磁盘

警告: 此类型的设置不适合作为启动设备,建议设置 Btrfs 分区以及单独的 EFI 系统分区。此外,GRUB 强烈反对安装到无分区磁盘。

Btrfs 可以占用整个数据存储设备,取代 MBRGPT 分区方案,使用 子卷来模拟分区。但是,并非必须使用无分区设置才能简单地在现有分区创建 Btrfs 文件系统,该分区是使用另一种方法创建的。无分区单磁盘设置有一些限制:

  • 无法在同一磁盘上的另一个分区上放置其他 文件系统
  • 由于前一点,在此磁盘上拥有 ESP 是不可能的。另一个设备对于 UEFI 启动是必要的。

要使用 Btrfs 覆盖现有的分区表,请运行以下命令:

# mkfs.btrfs /dev/sdX

例如,使用 /dev/sda 而不是 /dev/sda1。后者将格式化现有分区,而不是替换整个分区方案。由于根分区是 Btrfs,请确保 btrfs 已编译到内核中,或者将 btrfs 放入 mkinitcpio.conf#MODULES重新生成 initramfs

像对待带有 主引导记录的数据存储设备一样安装启动引导器。请参阅 Syslinux#手动GRUB/技巧和窍门#安装到分区或无分区磁盘。如果您的内核由于 Failed to mount /sysroot. 而无法启动,请在 /etc/default/grub 中添加 GRUB_PRELOAD_MODULES="btrfs"生成 grub 配置文件。

Ext3/4 到 Btrfs 转换

警告: 在 btrfs 邮件列表中有很多关于不完整/损坏/损坏转换的报告。请确保您拥有任何您无法承受丢失的数据的工作备份。有关更多信息,请参阅 Btrfs wiki 上的 Convert 页面。

从安装 CD 启动,然后通过执行以下操作进行转换:

# btrfs-convert /dev/partition

挂载分区并通过检查文件来测试转换。请务必更改 /etc/fstab 以反映更改(将类型更改为 btrfs,并将fs_passno [最后一个字段] 更改为 0,因为 Btrfs 在启动时不做文件系统检查)。另请注意,分区的 UUID 将已更改,因此在使用 UUID 时相应地更新 fstab。chroot 进入系统并重建启动引导器的菜单列表(请参阅 从现有 Linux 安装)。如果转换根文件系统,在仍然 chroot 的情况下,运行 mkinitcpio -p linux 以重新生成 initramfs,否则系统将无法成功启动。

注意: 如果出现任何问题,例如无法挂载或写入新转换的 Btrfs 的文件;只要备份子卷 /ext2_saved 仍然存在,始终可以选择回滚。使用 btrfs-convert -r /dev/partition 命令进行回滚;这将丢弃对新转换的 Btrfs 文件系统的任何修改。

在确认没有问题后,通过删除备份 ext2_saved 子卷来完成转换。请注意,如果没有它,您将无法恢复到 ext3/4。

# btrfs subvolume delete /ext2_saved

最后,平衡文件系统以回收空间。

请记住,一些先前安装的应用程序必须适应 Btrfs。

注意: Ext3/4 到 Btrfs 的转换是一个耗时的操作。对于 4 TiB 文件系统和普通 HDD,可能需要长达 10 个小时。

损坏恢复

警告: 工具 btrfs check 存在已知问题,请参阅 #btrfs check 部分

btrfs-check 不能在已挂载的文件系统上使用。为了能够在不从 Live USB 启动的情况下使用 btrfs-check,请将其添加到初始 ramdisk:

/etc/mkinitcpio.conf
BINARIES=(btrfs)

重新生成 initramfs:.

然后,如果启动出现问题,该实用程序可用于修复。

注意: 如果 fsck 进程必须使空间缓存(和/或其他缓存?)失效,则后续启动挂起一段时间是正常的(它可能会给出关于 btrfs-transaction 挂起的控制台消息)。系统应该在此后一段时间内恢复。

有关更多信息,请参阅 btrfs-check(8)

启动到快照

为了启动到快照,与将子卷挂载为根分区相同的过程适用,如 将子卷挂载为根分区 部分所述,因为快照可以像子卷一样挂载。

将 Btrfs 子卷与 systemd-nspawn 一起使用

请参阅 Systemd-nspawn#将 Btrfs 子卷用作容器根目录Systemd-nspawn#使用容器的临时 Btrfs 快照 文章。

减少访问时间元数据更新

由于 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
  • snapsyncSnapper 的同步工具。
https://github.com/doudou/snapsync || ruby-snapsyncAUR

以下软件包允许将 snapper 快照备份到非 Btrfs 文件系统。

  • snapborg — 类似于 borgmatic 的工具,它将 snapper 快照与 borg 备份集成。
https://github.com/enzingerm/snapborg || snapborgAUR

自动快照

对于 Btrfs 快照的管理和自动创建,可以使用快照管理器,例如 SnapperTimeshiftYabsnap

自动通知

桌面通知可帮助您立即注意到严重的 Btrfs 问题,与根本没有通知相比,可提供更好的感知。

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

  • 启动到任何只读快照或系统。
  • dmesg 日志中出现的 Btrfs 警告、错误或致命消息。

有关更多信息和配置,请参阅 https://gitlab.com/Zesko/btrfs-desktop-notification

故障排除

有关常规故障排除,请参阅 Btrfs 故障排除页面Btrfs 问题 FAQ

GRUB

分区偏移

当您尝试将 core.img 嵌入到已分区磁盘中时,可能会发生偏移问题。这意味着将 GRUB 的 core.img 直接嵌入到无分区磁盘(例如 /dev/sdX)上的 Btrfs 池中是没问题的

GRUB 可以启动 Btrfs 分区,但是该模块可能比其他文件系统更大。并且由 grub-install 创建的 core.img 文件可能不适合驱动器 MBR 和第一个分区之间的前 63 个扇区(31.5KiB)。最新的分区工具(如 fdiskgdisk)通过将第一个分区偏移大约 1MiB 或 2MiB 来避免此问题。

缺少 root

本文或本节的事实准确性存在争议。

原因: 建议手动编辑非配置文件。(在 Talk:Btrfs#不应建议编辑 /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 /storage.
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 提供更长的超时时间来轻松解决。例如:

/dev/sda                /storage    btrfs       rw,relatime,x-systemd.mount-timeout=5min  0 0

BTRFS: open_ctree failed

本文或本节的事实准确性存在争议。

原因: 状态已过时。用 systemd 替换 udev hook 没有意义,因为它们都使用 systemd-udevd。(在 Talk:Btrfs 中讨论)

截至 2014 年 11 月,systemdmkinitcpio 中似乎存在一个错误,导致在 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,而是将 btrfs 添加到 MODULES 数组中。然后重新生成 initramfs 并重新启动。

如果您尝试挂载缺少其中一个设备的 raid 阵列,您将得到相同的错误。在这种情况下,您必须将 degraded 挂载选项添加到 /etc/fstab。如果您的根目录位于阵列上,您还必须将 rootflags=degraded 添加到您的 内核参数

截至 2016 年 8 月,此 bug 的一个潜在解决方法是在 /etc/fstab 中仅挂载阵列中的一个驱动器,并允许 Btrfs 自动发现和附加其他驱动器。基于组的标识符(例如 UUID 和 LABEL)似乎会导致失败。例如,一个由 'disk1' 和 'disk2' 组成的双设备 RAID1 阵列将分配一个 UUID,但不要使用 UUID,而是在 /etc/fstab 中仅使用 /dev/mapper/disk1。有关更详细的说明,请参阅以下博客文章

另一个可能的解决方法是在 mkinitcpio.conf 中删除 udev hook,并将其替换为 systemd hook。在这种情况下,btrfs 不应 位于 HOOKSMODULES 数组中。

请参阅原始论坛帖子FS#42884 以获取更多信息和讨论。

btrfs check

本文或本节已过时。

原因: “正在积极开发” 的状态已过时。(在 Talk:Btrfs 中讨论)
警告: 由于 Btrfs 正在积极开发中,特别是 btrfs check 命令,因此强烈建议创建备份并在执行带有 --repair 开关的 btrfs check 之前查阅 btrfs-check(8)

btrfs-check(8) 命令可用于检查或修复未挂载的 Btrfs 文件系统。但是,此修复工具仍不成熟,即使对于那些不会导致文件系统无法挂载的错误,也无法修复某些文件系统错误。

持续的驱动器活动

内核 版本 6.2 起,默认设置 discard=async mount(8) 选项。据报告,这会导致某些驱动器即使在空闲时也会持续活动,因为丢弃队列的填充速度快于处理速度。这可能会导致功耗增加,尤其是在基于 NVMe 的驱动器上。

从内核版本 6.3 开始,默认丢弃 iops_limit 已从 100 更改为 1000,以解决此问题。您可以在旧内核版本上手动将其设置为所需的值,例如

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

其中 uuid 是 Btrfs 文件系统的 UUID。 1000 的限制将需要通过实验进行调整。

要在启动时设置参数,可以使用 systemd-tmpfiles,例如,通过创建以下文件

/etc/tmpfiles.d/btrfs-discard.conf
w /sys/fs/btrfs/uuid/discard/iops_limit - - - - 1000

或者,可以完全禁用异步丢弃,方法是在 fstab 中使用 nodiscard 挂载选项进行挂载,并改用 定期 TRIM

设备 total_bytes 应最多为 X,但找到 Y

如果驱动器已从另一台计算机移动或设备顺序已更改,并且报告的大小差异很小(最多几兆字节),则可能是 HPA(主机保护区域) 生效。

要验证是否启用了 HPA,请使用 hdparm

# hdparm -N DEVICE

输出提供两个数字:可见扇区数和实际扇区数。如果它们不同,则启用了 HPA。

如果主板强制设置此项,并且固件不提供关闭该选项的选项,则唯一的选择是缩小受影响的文件系统。这在原始计算机上或在任何不应用 HPA 的机器上最容易完成。

设备上没有剩余空间

博客文章 Fixing Btrfs Filesystem Full Problems 建议并解释了以下检查/步骤

  1. 立即清理空间(删除历史快照)
  2. 你的文件系统真的满了么?元数据和/或数据块不平衡(运行 btrfs balance
  3. 你的文件系统真的满了么?数据块不平衡
  4. 你的文件系统真的满了么?元数据不平衡
  5. 由于文件系统已满,无法运行 Balance(在运行 btrfs balance 之前,临时添加设备(例如 USB 密钥或循环设备)到 btrfs 文件系统,使用 btrfs device add

另请参阅