跳转至内容

Btrfs

来自 ArchWiki

本文或本章节已过时。

原因:btrfs Wiki,被显著链接到,自 2023 年 2 月起已存档,其链接应替换为相应的 BTRFS 文档 链接。(在 Talk:Btrfs 中讨论)

摘自 Btrfs 文档

Btrfs 是一款现代的 Linux 写时复制 (COW) 文件系统,旨在实现高级功能,同时关注容错、修复和便捷管理。
注意 与其他一些文件系统一样,Btrfs 仍在持续开发中。这意味着某些特定功能可能尚未完全适用于日常使用。要了解您的用例是否可能受到影响,请查阅 Btrfs 文档的 状态 和本文的 #已知问题 部分。

准备工作

对于用户空间实用程序,安装 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 默认的元数据节点大小 (nodesize) 为 16 KiB,而默认的数据扇区大小 (sectorsize) 等同于页面大小并自动检测。要为元数据使用更大的节点大小(必须是扇区大小的倍数,允许最大 64 KiB),请通过 -n 开关指定一个值给 nodesize 选项,如下例所示,使用 32 KiB 块

# mkfs.btrfs -L mylabel -n 32k /dev/partition
注意 根据 mkfs.btrfs(8) § OPTIONS,"较小的节点大小会增加碎片化,但会导致 B 树更高,进而降低锁定争用。较大的节点大小提供更好的数据打包和更少的碎片,但代价是更新元数据块时内存操作更昂贵"。

多设备文件系统

警告

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

# 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]

请参阅 #RAID,获取针对多设备 Btrfs 文件系统的维护建议。

配置文件

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

一些值得注意的配置文件

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

配置文件系统

写时复制 (CoW)

默认情况下,Btrfs 始终对所有文件使用 写时复制。写入操作不会就地覆盖数据;相反,块的修改副本会被写入新位置,并且元数据会更新以指向新位置。有关实现细节、优点和缺点的更多信息,请参阅 Btrfs 系统管理员指南部分

禁用 CoW

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

要在已挂载的子卷中禁用新创建文件的写时复制,请使用 nodatacow 挂载选项。这仅影响新创建的文件。对于现有文件,写时复制仍会发生。nodatacow 选项也会禁用压缩。详见 btrfs(5)

  • 摘自 btrfs(5) § MOUNT OPTIONS:"在单个文件系统内,无法将某些子卷以 nodatacow 挂载,而另一些子卷以 datacow 挂载。第一个被挂载的子卷的挂载选项适用于任何其他子卷。"
  • 即使禁用写时复制,在某些情况下仍可能被触发。详见下文 #CoW 仍被触发的情况

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

$ 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=never 选项的更多信息,请参阅下文 #对复制的影响
CoW 仍被触发的情况

如果一个带有 NOCOW 属性 (+C) 的文件具有多个引用(例如,通过 cp 使用 reflink 创建的副本,或 Btrfs 创建的快照),写时复制仍会被触发。

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因:5 级子小节太多。(在 Talk:Btrfs 中讨论)
对复制的影响

使用 cp 复制文件时,NOCOW 属性并非由源文件决定,而是由目标路径决定——要么继承自目录,要么取决于子卷是否以 nodatacow 选项挂载。仅当源文件和目标文件都具有或都不具有 NOCOW 属性时,才能进行 Reflink 复制。实际行为取决于 --reflink 选项,有三种可能的结果

  • 使用 --reflink=auto(默认):如果 NOCOW 属性匹配,则使用 reflink;否则,进行深度复制。
  • 使用 --reflink(或 --reflink=always):如果 NOCOW 属性匹配,则使用 reflink;如果不同,则操作失败。
  • 使用 --reflink=never:始终执行深度复制。

有关 --reflink 选项的更多信息,请参阅 cp(1)

对快照的影响

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

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

压缩

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

压缩类型

Btrfs 支持 zlib(由 zlib 提供 DEFLATE)、lzoLZO)以及 zstd(由 zstd 实现 Zstandard)等压缩算法。LZO 没有压缩级别,而 zlib 和 zstd 具有可调节的压缩级别(zlib:1-9;zstd:-15 到 -1,1-15,必须是整数)。更高级别提供更好的压缩效果,但需要更多处理时间。更改级别会对 CPU 和 I/O 吞吐量产生不同的影响,因此应在更改前后进行检查/基准测试。有关压缩类型的更多信息,请参阅 btrfs(5) § COMPRESSION

警告 使用较旧内核或 btrfs-progs 且不支持 zstd (特别是级别 -15 到 -1)的系统,如果使用此选项,可能无法读取或修复您的文件系统。

启用压缩

针对文件系统

挂载选项 compress=alg[:level] 启用对文件系统每次写入操作自动考虑压缩,其中 algzliblzozstd,或 no(表示不压缩),可选的 level 指定压缩级别(未指定或设为 0 时默认为 3;不适用于 lzo)。使用此选项,Btrfs 将检查压缩文件写入的第一个数据块是否能使其缩小。如果可以,该文件的整个写入操作都将被压缩。如果不能,该文件将被标记为 NOCOMPRESS,并且当前写入以及对该文件的所有后续写入都不会被压缩 [4]。这样做是为了防止磁盘等待所有要写入的数据完全提供给 Btrfs 并尝试压缩后才开始写入。

  • 压缩挂载选项在同一文件系统的所有挂载点(包括不同的子卷和绑定挂载)之间共享 [5]
  • 如果对文件的某次写入无法压缩,则后续写入也将不被压缩。

或者,您可以在 btrfs 子卷上设置压缩属性,它将持久存在并无论如何挂载都生效,使用 btrfs property set / compression alg,其中 alg 可以是 zstdzstd:n,其中 n 是压缩级别。

本文章或章节需要扩充。

原因:以下段落中提到的“经验测试”缺少引用,且原文中的百分比描述不准确。(在 Talk:Btrfs 中讨论)

挂载选项 compress-force=alg[:level] 可以替代使用,它使 Btrfs 检查每次写入的每个数据块,并决定是否单独压缩它们。对多个混合使用系统的经验测试表明,使用 compress-force=zstd 相比 compress=zstd 可以显著提高空间节省(从 10% 到 20%),但这会导致(轻微的)CPU 使用率更高和写入时间更长,而没有达到预期目的。但是,强制压缩与 官方 Btrfs 指南 相悖。

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

提示 在将 Arch 安装到空的 Btrfs 分区时启用压缩,请在安装前 挂载 文件系统时使用 compress 选项:mount -o compress=zstd /dev/sdxY /mnt/。在配置过程中,将相同的 compress 挂载选项添加到 fstab 中的根文件系统。
针对现有文件

要对现有文件应用压缩,请使用 btrfs filesystem defragment -calg 命令,其中 algzliblzozstd。要指定压缩级别,请使用 -L 选项,否则使用默认级别(不适用于 lzo)。例如,要使用 zstd 和压缩级别 1 重新压缩所有文件,请运行以下命令

# btrfs -v filesystem defragment -r -czstd -L1 /
警告 对具有 COW 副本(无论是快照副本还是用 cp 创建的副本)的文件进行碎片整理,可能导致两个不相关的文件,从而可能大大增加磁盘使用量。

使用上述方法压缩文件并非持久性的;其他写入操作将应用原始的压缩设置。

以下两种方法可以为单个文件持久启用压缩

$ chattr +c file
$ btrfs property set file compression zstd

第一个命令使用从 ext2 文件系统继承的文件属性的传统接口,不灵活,默认使用 zlib 压缩算法。第二个命令可以指定压缩算法,但尚未实现指定压缩级别,因此使用默认级别 3(不适用于 lzo)。

查看压缩类型和比例

compsize 接受文件或目录列表(或整个 Btrfs 文件系统)作为输入,并输出使用的压缩类型和实际压缩比(压缩大小/未压缩大小)。未压缩大小可能与 du(1) 等其他程序给出的数字不匹配,因为每个 extent 只计算一次,即使它有多个 reflinks,或者其中部分不再被使用但尚未被垃圾回收。

选项 -x 可以将其限制在单个文件系统上,这在 compsize -x / 等情况下非常有用,可以避免它尝试访问非 Btrfs 子目录并导致整个运行失败。

子卷

"Btrfs 子卷不是块设备(也不能被视为块设备),相反,Btrfs 子卷可以被视为一个 POSIX 文件命名空间。这个命名空间可以通过文件系统的顶层子卷访问,也可以独立挂载。" [6]

每个 Btrfs 文件系统都有一个 ID 为 5 的顶层子卷。该子卷不能被移除或替换为其他子卷。顶层子卷在文件系统中的路径为 /,其他子卷则嵌套在顶层子卷之下。然而,子卷可以在文件系统中移动,其路径可能会改变,但其 ID 不会。

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

子卷的一个主要用例是 快照

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

创建子卷

要创建子卷,Btrfs 文件系统必须已挂载。

# btrfs subvolume create /path/to/subvolume
  • 您可以使用 --parents 选项自动创建父目录(如果它们不存在)。
  • 如果顶层子卷未挂载,并且您想在其内部创建子卷,可以通过指定 subvolid=5 临时挂载它。详见 #挂载子卷

列出子卷

要查看 path 所属文件系统的所有子卷列表,请执行

# btrfs subvolume list -t path

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

删除子卷

要删除子卷

# btrfs subvolume delete /path/to/subvolume

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

警告 在删除子卷之前,请确保它未被挂载。删除已挂载的子卷可能导致文件系统不一致。

挂载子卷

子卷可以使用 subvol=/path/to/subvolumesubvolid=objectid 挂载选项进行挂载。可以通过在文件系统顶层下创建各种子卷,然后将它们挂载到适当的挂载点来模仿传统的文件系统分区。

例如,以下命令将顶层子卷挂载到 /mnt/,并创建两个名为 subvol_rootsubvol_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 挂载选项引用子卷需要使用相对于顶层子卷的路径。这可能与顶层子卷的挂载路径不同。

提示
  • 最好使用 subvol=/path/to/subvolume 进行挂载,而不是使用 subvolid,因为在恢复 #快照 时,subvolid 可能会改变,需要更改挂载配置。
  • 不将顶层子卷 (ID=5) 用作 /(默认情况下是这样做的)可以简化子卷布局的更改。相反,考虑创建一个子卷来存放您的实际数据并将其挂载为 /
注意 摘自 btrfs(5) § MOUNT OPTIONS:"大多数挂载选项适用于整个文件系统,并且只有第一个被挂载的子卷的选项才会生效。这是由于缺乏实现,将来可能会改变。"

请参阅 Snapper#建议的文件系统布局Btrfs 系统管理员指南#管理快照,以及 系统管理员指南#布局,了解使用子卷的文件系统布局示例。

将子卷挂载为根目录

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

更改默认子卷

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

# btrfs subvolume set-default subvolume-id /

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

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

  • GRUBgrub-mkconfig 脚本尊重 Btrfs 默认子卷设置。如果 / 是顶层子卷,它将永远不会指定 subvol=/subvolid=5 挂载选项,这可能导致启动失败。如果 / 不是顶层子卷,它将始终指定相应的 subvol 选项,这使得简单地设置默认子卷无法回退(bug 报告)。目前这可以通过手动修改 grub.cfg 中的 rootflags 内核参数(参见 #挂载子卷)来解决,或者使用工具自动为 GRUB 中的快照创建启动项(参见 #从快照启动)。此外,如果 grub.cfg 的实际位置发生变化,例如包含 /boot 的子卷发生变化时,您需要再次运行 grub-install。参见 此论坛帖子
  • 如果您计划使用 同步和备份程序,建议不要更改默认子卷,因为在恢复除默认子卷之外的任何子卷的快照时可能会导致问题。例如,Timeshift 会在文件系统的默认子卷的相对路径 timeshift-btrfs 存储快照,因此,为根目录和家目录设置一个单独的非默认子卷是首选做法。

配额

“磁盘配额”的概念在 Unix 世界有着悠久的传统。传统的配额基于文件所有权,通过限制用户拥有的所有文件的总大小来控制空间使用。这种方法对文件管理来说是直接的,但在目录级别的限制上存在局限性,通常需要在安装时进行分区且缺乏动态调整能力。Btrfs 采用了与传统 Unix 系统不同的配额设计理念,不支持传统的 用户或组-based 配额功能。这是因为其现代存储特性(如 #快照#写时复制 (CoW)#数据去重,以及 #压缩)使得传统配额的空间计算变得极其复杂和不准确 [8]。作为替代方案,Btrfs 采用基于子卷的配额机制,目前提供两种实现方法——传统的 #配额组 (qgroups) 和较新的 #简单配额 (squotas)(于 2023 年底发布的内核 6.7 中引入)来实现类似的空间管理效果。虽然这增加了管理复杂性,但它提供了更灵活和精确的存储控制能力,允许在不进行分区的情况下限制目录大小,并实现动态配额调整。

注意 配额管理仅在挂载 Btrfs 文件系统(或其任何子卷)后才可能进行。

配额组 (qgroups)

警告 尽管 Btrfs qgroups 被认为是稳定的通用功能,但在频繁创建大量快照的环境中启用 qgroups 仍然可能导致性能下降,尤其是在快照删除期间。qgroup 记账会引入额外的元数据开销,并可能在高强度快照工作负载下影响系统响应能力。

近期内核改进(5.15 及更高版本)已经修复了许多 历史问题,但 一些限制仍然存在,尤其是在高级应用场景中,如深度嵌套的子卷或复杂的 qgroup 层次结构。自 2016 年以来这里提出的建议——在启用 qgroups 之前仔细评估特定用例——至今仍然适用。请务必查阅最新的 Btrfs 文档 获取当前详细信息。值得注意的是,为了解决 qgroups 的性能问题,Btrfs 引入了 #简单配额 (squotas) 功能,提供了一种灵活性稍低但性能更好的替代解决方案。

Btrfs 的精确配额支持通过子卷之上的 qgroups 实现。qgroups 使用 qgroupids 表示,格式为 level/ID。子卷的级别为 0,其中 0/ 可以省略,对应的 ID 是子卷 ID。例如,0/5 表示顶层子卷的 qgroup。子卷路径也可以代替 0/ID 表示。qgroups 形成一个状层次结构,但一个 qgroup 可以有多个父 qgroup [9]。叶子 qgroup 的级别为 0,直接对应于子卷。所有更高级别 qgroup 的 ID 可以自由指定。更高级别 qgroup 包含更低级别 qgroup,同级别组不能嵌套,但级别不表示嵌套深度。例如,子 qgroup 0/5 可以分配给 qgroup 5/100

总引用空间和独占引用空间

每个 qgroup 主要跟踪两个值:总引用空间量和独占引用空间量。总引用空间指的是从 qgroup 内部可访问的所有数据所占用的存储空间,而独占引用空间指的是仅由属于该 qgroup 的子卷引用(且不被 qgroup 外部的子卷引用)的数据所占用的存储空间。

启用/禁用 qgroups

使用以下命令为包含 path 的文件系统启用 qgroups

# btrfs quota enable path

enable 改为 disable 即可禁用 qgroups。

警告 禁用 qgroups 将销毁所有当前 qgroups 并移除它们的关系。
创建/销毁 qgroups

对应于子卷的 0 级 qgroups 总是自动创建的。即使在启用配额之前创建了子卷,在启用配额时也会自动创建相应的 qgroups。同样,当 删除子卷 时,相应的 qgroups 将被删除,并自动与最初包含这些 qgroups 的更高级别 qgroups 解除关联。

使用以下命令在包含 path 的文件系统中创建 qgroup qgroupid

# btrfs qgroup create qgroupid path

create 改为 destroy 即可销毁 qgroup。销毁 qgroup 类似于使用 rm -d 删除目录——如果 qgroup 有子 qgroup,必须先移除关系;如果只有父 qgroup 存在,则会自动移除关系。

注意 对应于子卷的 qgroups 不能直接删除,而应该通过直接删除子卷来自动删除。
分配/移除子 qgroups

使用以下命令在包含 path 的文件系统中将 src 分配为 dst 的子 qgroup,请注意 dst 必须比 src 处于更高级别

# btrfs qgroup assign src dst path

assign 改为 remove 即可移除此关系。

注意 在分配/移除子 qgroups 后,可能需要进行 #配额重新扫描,这在当前版本中是自动触发的,但可能导致性能开销。详见 #配额重新扫描 部分。
限制/解除限制 qgroups

您可以限制 qgroups 的总引用空间或独占引用空间,或同时限制两者。例如,使用以下命令将包含 path 的文件系统中 qgroupid总引用空间限制为不超过 1GiB

# btrfs qgroup limit 1G qgroupid path
注意 如果 启用了压缩,Btrfs 目前仅支持限制压缩数据所占用的空间。

如果省略 qgroupid,它将尝试将 path 解释为子卷路径。添加 -e 选项(在 limit 之后)以限制独占引用空间。将 size 改为 none 即可移除限制。

列出 qgroups

使用以下命令列出包含 path 的文件系统中的所有 qgroups

# btrfs qgroup show path
注意 由于 btrfs qgroup show 使用磁盘数据,可能需要先执行 sync 才能显示准确的统计信息。为此,您可以添加 --sync 选项(在 show 之后)以首先对包含 path 的文件系统执行强制同步操作。

输出中的“Path”列可能显示一些特殊值,其含义如下

  • <toplevel>:对应于顶层子卷的 Qgroup。
  • <under deletion>:此 qgroup 对应的子卷已被删除(其目录已移除),但子卷元数据尚未完全清理。
提示 您可以使用 btrfs subvolume sync path subvolid 等待包含 path 的文件系统中子卷的完全删除(可以指定多个子卷 ID;如果未指定,则等待文件系统中所有当前待处理的子卷删除完成)。但是,请注意先卸载子卷。
  • <squota space holder>:(仅适用于 #简单配额 (squotas))对应此 qgroup 的子卷已完全删除,但相关统计信息仍被保留。这是因为简单配额只将 extents 归因于首先分配它们的子卷,尽管该子卷已被完全删除,但这些 extents 仍被其他子卷引用。

根据您的需要,您可以添加一些显示选项(在 show 之后)。常见选项包括

  • -p:显示父 qgroups。
  • -c:显示子 qgroups。
  • -r:显示总引用空间限制。
  • -e:显示独占引用空间限制。
  • -f:仅列出与包含 path 的子卷对应的 qgroups。
  • -F:仅列出与包含 path 的子卷对应的 qgroups,以及包含这些 qgroups 的更高级别 qgroups。

有关更多选项,请参阅 btrfs-qgroup(8) § show

配额重新扫描

配额重新扫描 读取文件系统中所有 extents 的元数据,并相应更新每个 qgroup 的统计信息。

Btrfs qgroups 能够处理许多复杂的 extent 共享和非共享场景(包括子卷和子 qgroup 的删除),同时保持总引用空间和独占引用空间的准确计数。然而,当 qgroup 关系发生变化(手动 分配/移除子 qgroups)时,由于记录数据不足(只记录总引用空间和独占引用空间,没有明确记录哪些 extent 属于共享或独占),通常需要对整个文件系统进行配额重新扫描。此时,qgroups 将被标记为“不一致”,表示需要进行配额重新扫描的状态。

当前实现中唯一的例外是,当 qgroup 的总引用空间等于其独占引用空间时,这意味着所有数据都是独占的。在这种情况下,当对此子卷执行分配/移除操作时,只需同时将此 qgroup 的引用空间加/减到父 qgroup 的总引用空间和独占引用空间中。

从内核版本 4.19 开始,手动 分配/移除子 qgroups 会自动触发配额重新扫描(必要时)。然而,由于配额重新扫描的开销很高,一次只能执行一次,并且此方法无法在返回前等待重新扫描完成,因此您可以添加 --no-rescan 选项(在 assign/remove 之后)以避免自动触发,并在之后手动触发。

提示 在使用 --no-rescan 选项进行 分配/移除子 qgroups 后,如果需要配额重新扫描,将会显示相应的警告。警告也可以通过 #列出 qgroups 显示。

使用以下命令手动触发包含 path 的文件系统的配额重新扫描

# btrfs quota rescan path

该命令立即返回。添加 -w--wait)选项(在 rescan 之后)以等待重新扫描完成(即使已开始)再返回。使用 -W--wait-norescan)选项仅等待当前正在运行的重新扫描完成。使用 -s--status)选项返回当前进度。

简单配额 (squotas)

Qgroups 能够处理许多复杂的 extent 共享和非共享场景(包括子卷和子 qgroup 的删除),同时保持总引用空间和独占引用空间的准确计数。然而,这种灵活性是有代价的:许多计算操作本质上是全局的,这意味着当 extent 引用关系改变时,它们会影响所有引用该 extent 的 qgroups 的统计信息。这可能导致事务提交速度变慢和不可接受的延迟,尤其是在快照数量急剧增加时。

为了解决 qgroups 的这一限制,Btrfs 支持第二套配额语义:简单配额 (squotas)。Squotas 重用了 qgroup API 和分层结构模型,但不跟踪共享和独占使用。相反,squotas 将所有 extents 归因于首先分配它们的子卷。通过引入少量新的元数据记录,这使得所有记账决策都能在涉及数据块本身分配或释放的操作中局部完成,完全避免了复杂且耗时的反向引用解析过程。

Squotas 需要在文件系统级别启用,只需在 启用 qgroups 命令中添加 -s--simple)选项(在 enable 之后)。请注意,如果 qgroups 已经启用,您需要先 禁用 qgroups 然后再启用 squotas,否则将不会生效 [10]。由于其简单的计算方法,squota 模式不需要(也无法)执行 #配额重新扫描。除了这两点,squotas 的操作方式与 qgroups 完全相同,但显示和限制的所谓“总引用空间”和“独占引用空间”都是通过上述方法(将所有 extents 归因于首先分配它们的子卷)计算得出的值。由于 squotas 需要记录首先分配 extents 的子卷,因此它们仅对启用后写入的 extents 生效。如果在非空文件系统上启用 squotas,首次启用时统计信息将为 0,因此只有在空子卷上启用 squota 限制然后写入数据才能确保准确的统计信息。

提交间隔

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

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

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

SSD TRIM

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

异步 discard 可以安全地与周期性 trim 同时使用 [11]

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

用法

Swap 文件

Btrfs 和 Linux 交换子系统在实现上存在一些限制 [12]

  • 不支持跨多个设备的交换文件
  • 数据 配置文件 必须为 single
  • 不能为包含活动交换文件的子卷创建快照
  • 交换文件必须预分配(即,无空洞)
  • 写时复制必须 禁用 针对交换文件单独禁用(即,交换文件必须具有 NOCOW 属性)

交换文件的最后两个限制由 btrfs filesystem mkswapfile 命令自动处理。

有关交换文件的常规信息,请参阅 交换#交换文件

要在 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。

激活 Swap 文件

# swapon /swap/swapfile

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

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

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

有关删除交换文件和其他详细信息,请参阅 交换#交换文件

提示 要使用休眠功能,除了配置交换文件外,还需要完成 电源管理/挂起与休眠 中描述的额外步骤。

显示已用/可用空间

一般的 Linux 用户空间工具,例如 df(1),将不准确地报告 Btrfs 分区上的可用空间,因为它们不考虑文件和元数据的使用情况。建议使用 btrfs filesystem usage 查询 Btrfs 分区。例如,要查看设备分配和使用情况的完整细分统计

# btrfs filesystem usage /
注意 btrfs filesystem usagebtrfs filesystem df 如果 RAID5RAID6 配置文件 与同一文件系统中的其他配置文件(例如元数据使用 DUP 而数据使用 RAID5)共存,则显示不准确的结果 [13]

或者,btrfs filesystem df 允许快速检查已分配空间的使用情况,无需 root 权限

$ btrfs filesystem df /

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

同样的限制也适用于分析文件系统子集空间使用情况的工具,例如 du(1)ncdu(1),因为它们不考虑 #写时复制 (CoW) 或透明 #压缩。相反,请参阅 btduAURcompsize,以获取支持 Btrfs 的替代工具。

碎片整理

Btrfs 通过挂载选项 autodefrag 支持在线碎片整理;请参阅 btrfs(5) § MOUNT OPTIONS。要手动对根目录进行碎片整理(不深入到子卷、挂载点和目录符号链接),请使用

# btrfs filesystem defragment -r /
警告 碎片整理将破坏 #写时复制 (CoW) 数据的 reflink(例如使用 cp 复制的文件、#快照去重 的数据)。这可能导致空间使用量显著增加,具体取决于被破坏的 reflink [15]
注意 不带 -r 的目录参数不会递归地整理文件碎片,但会整理某些内部树(extent 树和子卷树)的碎片。这曾经令人困惑,将来可能会被移除。
提示 您可以同时使用 -c-L 指定压缩;详见 #针对现有文件

RAID

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

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

擦洗 (Scrub)

本文章或章节需要扩充。

Btrfs Wiki 词汇表 Btrfs Wiki Glossary 指出 Btrfs scrub 是"[一]个在线文件系统检查工具。它读取文件系统上的所有数据和元数据,并利用校验和以及 RAID 存储中的重复副本,以识别和修复任何损坏的数据。"

注意 正在运行的 scrub 进程将阻止系统挂起,详见 此线程
手动启动

要在包含 / 的文件系统上启动(后台)scrub,请执行

# btrfs scrub start /

检查正在运行的 scrub 状态

# btrfs scrub status /
通过服务或定时器启动

btrfs-progs 包提供了 btrfs-scrub@.timer 单元,用于每月擦洗指定的挂载点。启用 计时器,并使用转义路径,例如 btrfs-scrub@-.timer 用于 /,而 btrfs-scrub@home.timer 用于 /home。您可以使用 systemd-escape -p /path/to/mountpoint 转义路径;详见 systemd-escape(1)

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

在散热不足的大容量 NVMe 驱动器上(例如在笔记本电脑中),擦洗操作可能会以足够快的速度和足够长的时间读取驱动器,使其变得非常热。如果您使用 systemd 运行擦洗操作,您可以通过 systemd.resource-control(5) 中描述的 IOReadBandwidthMax 选项通过使用 drop-in 文件 轻松限制擦洗速率。

平衡 (Balance)

"平衡操作会将文件系统中的所有数据再次通过分配器。它主要用于在添加或移除设备时,重新平衡文件系统跨设备的数据。如果设备发生故障,平衡操作将为冗余 RAID 级别重新生成丢失的副本。" [16] 参见 上游 FAQ 页面

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

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

快照

"快照本质上是一个子卷,它利用 Btrfs 的 COW 能力,与另一个子卷共享其数据(和元数据)。” 参见 Btrfs Wiki 系统管理员指南#快照Btrfs 文档 了解详情。

创建快照

# btrfs subvolume snapshot 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

发送的快照必须是只读的。上述命令对于将子卷复制到外部设备(例如,挂载在 /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

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

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

去重

Btrfs 利用写时复制功能,能够在不实际复制数据的情况下复制文件或整个子卷。然而,每当文件被修改时,就会创建一个新的实际副本。数据去重更进一步,它主动识别共享公共序列的数据块,并将它们合并到一个具有相同写时复制语义的 extent 中。

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


Bees

Bees 是一个根守护进程,它在块级别对 Btrfs 文件系统进行数据去重,忽略文件和子卷的实际布局。因此,它可以在不同用户之间进行文件去重而用户不会察觉,也可以在系统文件和 podman 容器之间进行去重,并对部分不同的文件中相同的部分进行去重。

要运行 bees,请安装并配置它。bees 的一个实例只能处理一个文件系统,因此要处理多个文件系统,您需要运行多个 bees 实例并使用不同的配置文件。在 /etc/bees/ 中,创建 beesd.conf.sample 的副本,名称可随意但以 .conf 结尾,例如:beesd_myroot.conf。编辑此文件。您必须提供要进行重复数据删除的文件系统的 UUID(以 root 身份使用 lsblk -f 查找)。您还必须决定此 Bees 实例将占用多少 RAM。该值会影响 Bees 将检测到的重复块的最小大小。有关示例,请参阅配置文件中的注释。将该值写入 DB_SIZE 变量。

启动/启用 Bees beesd@aaaa-bbbb-cccc-dddd.service,其中 aaaa-bbbb-cccc-dddd 限定符是 UUID。如有需要,请使用 journalctl 查看其日志。

注意 如果快照是在 Bees 未运行时创建的,Bees 无法对已创建快照的文件进行重复数据删除。在已完全快照的文件系统上运行 Bees 会导致已用空间增加而非减少。在启动 Bees 之前或之后删除所有现有快照,并根据需要之后再创建新快照。如果您在启动后自动创建快照,请确保快照是在 Bees 完全启动后进行的。此外,在文件系统上进行大型平衡操作时(例如在 RAID 中添加或替换驱动器时),请停止 Bees。[17]

调整大小

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

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

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

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

# btrfs filesystem resize max /

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

# btrfs filesystem resize size /

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

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

已知问题

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

加密

Btrfs 没有内置加密支持,但目前正在努力 [18] 集成基于 Fscrypt 的加密功能。

然而,用户可以在运行 mkfs.btrfs 之前加密分区,请参阅 dm-crypt/Encrypting an entire system。另一种方法是堆叠文件系统加密

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 配置。

转换

警告 btrfs 邮件列表中有许多关于不完整/损坏/失效转换的报告。请确保您对任何无法承受损失的数据拥有可用的备份。有关更多信息,请参阅 Btrfs Wiki 上的 转换 页面。
注意 将现有文件系统转换为 Btrfs 是一个耗时的操作。对于一个 4 TiB 的文件系统和普通 HDD,可能需要长达 10 小时。

Ext3/4 到 Btrfs 的转换

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

# btrfs-convert /dev/partition

挂载分区并通过检查文件来测试转换。务必更改 /etc/fstab 以反映更改(将 type 改为 btrfs,将 fs_passno ——最后一个字段——改为 0,因为 Btrfs 在启动时不做文件系统检查)。另请注意,分区的 UUID 将会改变,因此在使用 UUID 时请相应地更新 fstab。chroot 进入系统并重建引导加载程序的菜单列表(请参阅 从现有 Linux 安装)。如果正在转换根文件系统,请在 chroot 环境中重新生成 initramfs,否则系统将无法成功启动。

  • 如果出现任何问题,无论是无法挂载还是无法写入新转换的 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 个空闲块)。然后再次尝试转换。请参阅 上游错误报告

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

# btrfs subvolume delete /ext2_saved

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

NTFS 到 Btrfs 的转换

NTFS 可以使用 ntfs2btrfsAURntfs2btrfs-gitAUR 进行转换。

卸载目标文件系统并运行转换,可以指定确切的压缩和校验和类型

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

如果转换后一切正常,您可以删除 image/ntfs.img 镜像,否则该镜像将用于恢复原始文件系统。

转换后

警告 仅在确认您不会恢复到原始文件系统后才执行这些步骤,因为即使您保留了恢复文件,这些步骤也会使恢复变得不可能。

将现有文件系统转换为 Btrfs 后,您可以采取一些步骤。

使文件数据更连续

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

#平衡 以使 Btrfs 元数据更紧凑

损坏恢复

警告 工具 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 将备份增量发送到外部驱动器。请参阅它们的文档,了解实现、功能和要求的差异。

  • snbksnapper 提供的一个命令行工具,用于将 snapper 快照复制到远程或本地备份。
http://snapper.io/ || snapper
  • btrbk — 用于创建 Btrfs 子卷快照和远程备份的工具。
https://github.com/digint/btrbk || btrbk
  • snap-sync — 使用 Snapper 快照备份到外部驱动器或远程机器。
https://github.com/wesbarnett/snap-sync || snap-syncAUR

以下软件包允许将 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

空间缓存 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

转换结果可以在 systemd journal 日志中查看,例如:

kernel: BTRFS info (device ...): creating free space tree
kernel: BTRFS info (device ...): setting compat-ro feature flag for FREE_SPACE_TREE (0x1)
kernel: BTRFS info (device ...): setting compat-ro feature flag for FREE_SPACE_TREE_VALID (0x2)
kernel: BTRFS info (device ...): cleaning free space cache v1
kernel: BTRFS info (device ...): enabling free space tree
注意 转换后,Btrfs 会在文件系统上设置一个 compat-ro 功能标志。因此,这个文件系统可能无法再被非常旧的 Btrfs 内核实现所挂载。

故障排除

有关一般故障排除,请参阅 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 来避免此问题。

启动时间长

有时,大型(> 4TB)Btrfs 卷可能需要很长时间才能挂载,从而减慢启动速度。将组树(group tree)更改为块组树(block group tree)可以帮助解决此问题

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

挂载超时

有时,特别是在大型 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 失败

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

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

截至 2014 年 11 月,systemdmkinitcpio 中似乎存在一个错误,导致在使用 mkinitcpio.conf 中的 btrfs 钩子的多设备 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' 和 'disk2' 组成的双设备 RAID1 阵列将分配一个 UUID,但不要使用该 UUID,而应仅在 /etc/fstab 中使用 /dev/mapper/disk1。有关更详细的解释,请参阅以下博客文章

另一个可能的解决方法是删除 mkinitcpio.conf 中的 udev 钩子,并用 systemd 钩子替换它。在这种情况下,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 版本,默认的 discard 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 的机器上完成。

设备上没有剩余空间

博客文章 修复 Btrfs 文件系统满的问题 建议并解释了以下检查/步骤

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

有关 ENOSPC(“磁盘空间不足”)的最新说明,请参阅 ENOSPC - 无可用磁盘空间 | Forza 的漫谈

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.