Btrfs (简体中文)

From ArchWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
翻译状态:本文是 Btrfs翻译。上次翻译日期:2020-10-19。如果英文版本有所更改,则您可以帮助同步翻译。

引自 Btrfs Wiki

Btrfs 是一种现代的写时复制(CoW)Linux 文件系统,已经并入内核主线。Btrfs 致力于实现一些高级功能,同时着重于容错性、修复性以及易于管理性。它由多家企业共同开发,以 GNU GPL 协议授权,并欢迎任何人的贡献。
警告:

准备工作

要使用一些用户空间工具的话,需要 安装 基础操作必须的 btrfs-progs 软件包。

如果需要从 Btrfs 文件系统引导(比如说内核和内存盘在一个 Btrfs 的分区上),请检查 启动引导器 是否支持 Btrfs。

创建文件系统

下文展示了如何创建一个新的 Btrfs 文件系统。要将一个 ext3/4 分区转换为 Btrfs,请参考 #从 Ext3/4 转换。要使用无分区的配置,请参考 #无分区 Btrfs 磁盘

查阅 mkfs.btrfs(8) 以获取更多信息。

单一设备上的文件系统

要在分区 /dev/partition 上创建一个 Btrfs 文件系统,执行:

# mkfs.btrfs -L mylabel /dev/partition

Btrfs 用于元数据的默认节点大小 (nodesize) 为 16KB,而用于数据的默认扇区大小 (sectorsize) 等于页面大小 (page size) 并会自动检测。 要对元数据使用较大的节点大小 (必须为扇区大小的倍数,最大允许 64KB),请通过 -n 开关为 nodesize 指定一个值。如下例所示,使用 32KB 块大小:

# mkfs.btrfs -L mylabel -n 32k /dev/partition
注意: 根据 mkfs.btrfs(8) § OPTIONS 手册页内容:“较小的节点大小会增加碎片,但也会让 B-trees 更高,进而使得锁定争用(locking contention)更少。较高的节点大小则能有更好的打包(packing)和更少的碎片,但代价是,更新元数据块时会使用更多的内存”。

多设备文件系统

警告: Btrfs 的 RAID 5 和 RAID 6 模式存在致命缺陷,除非用来做数据丢失测试,否则不应当用于任何场景。这里有已知问题和部分解决方法的列表。 查阅 Btrfs Wiki 网页上关于 RAID 5 和 RAID 6 的说明 以获取最新动态(似乎不更新了)。

多个设备可以用来创建一组 RAID。支持的 RAID 级别有 RAID 0、RAID 1、RAID 10、RAID 5 和 RAID 6。从 5.5 版本内核开始,新增对 RAID1c3RAID1c4 的支持,分别是 3 份冗余和 4 份冗余的 RAID 1。可以使用 -d-m 参数分别为数据和元数据配置 RAID 等级。默认情况下,数据有一份副本(single),元数据则被镜像(RAID1)。这就像创建一个 JBOD 配置,多个磁盘会被看做成一个文件系统,但文件不会重复。更多有关如何创建一个 Btrfs RAID 卷的信息请参阅 Btrfs Wiki:在多个设备上使用 Btrfs

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

必须在 /etc/mkinitcpio.conf 中加入 udev 钩子或 btrfs 钩子才能在一个池中使用多个 Btrfs 设备。查阅 Mkinitcpio (简体中文)#常用钩子 以获取更多信息。

注意:
  • 可以稍后再将设备添加到多设备文件系统中。详情请参见 Btrfs wiki 文章
  • 多个设备可以大小各异。但是,如果在 RAID 配置中一个硬盘的大小比其他的都大,那么它多出的空间将不会被使用。
  • 有些 引导加载程序 不支持多设备文件系统,比如 Syslinux
  • Btrfs 不会自动从速度最快的设备读取,因此混合使用不同类型的磁盘会导致性能表现不恒定。详情请参阅 Stack Overflow 上的这个回答

#RAID 小节中有关于维护多设备上的 Btrfs 文件系统的一些建议。

配置文件系统

写时复制 (CoW)

默认情况下 Btrfs 对所有文件使用 写时复制 (CoW)。参阅 Btrfs 系统管理指南相关章节 以获取实现细节以及它的优点和缺点。

停用 CoW

要对某个子卷上的新文件停用写时复制,使用 nodatacow 挂载选项。这只会影响新创建的文件,写时复制仍然会在已存在的文件上生效。nodatacow 参数同样会禁用压缩。参阅 btrfs(5) 以了解细节。

注意: 引自 btrfs(5) § MOUNT OPTIONS:“在单个文件系统中,无法使用 nodatacow 参数挂载某些子卷,而其他的使用 datacow 参数。第一个被挂载子卷的挂载参数将会应用于其他所有子卷。”

要单文件或目录禁用写时复制特性,请使用下面的命令:

$ chattr +C [文件/目录的地址(path)]

这会为这个文件的单个引用停用写时复制,如果这个文件不只有一个引用(例如通过 cp --reflink=always 生成或者在文件系统快照中),写时复制依然生效。

注意: 引自 chattr 的手册页:“在 Btrfs 上,'C' 标志应该被设置在新建的或者是空白的文件/目录,如果被设置在已有数据的文件,当块分配给该文件时,文件将不确定是否完全稳定。如果 'C' 标志被设置给一个目录,将不会影响目前的目录,但在该目录创建的新文件将具有 No_COW 属性。”
提示: 可以用下面的方法为已存在的文件或目录停用写时复制:
$ mv /path/to/dir /path/to/dir_old
$ mkdir /path/to/dir
$ chattr +C /path/to/dir
$ cp -a /path/to/dir_old/* /path/to/dir
$ rm -rf /path/to/dir_old

需要保证这个过程中目标文件不会被使用,同时注意下面描述的 mvcp --reflink 并不起作用。

创建轻量副本

默认情况下,使用 cp 复制 Btrfs 文件系统上的文件时,会创建实际副本。要创建引用原始数据的轻量级副本,请使用 reflink 选项:

$ cp --reflink source dest 

参阅 cp 的手册页获得关于 --reflink 标志的更多信息。

压缩

Btrfs 支持 透明和自动压缩。这就减小了文件的大小,通过减少文件写入增幅来显著延长闪存介质(flash-baesd media)的寿命 [1][2][3]。在某些特定的场景下(比如单线程、重负荷的文件 I/O))还 提高了性能。尽管在其他的场景下(比如多线程和/或大文件 I/O 高强度 CPU 任务)还是明显影响了性能。通常使用更快的压缩算法,比如 zstdlzo 可以获得更好的性能,这个 性能测试 提供了详细的对比。

承上文,compress=alg 挂载选项可自动考虑为每个文件启用压缩,其中的 alg 处可以选填为 zlib, lzo, zstd, 或者 no(即不压缩)。由此,Btrfs 将检查压缩数据的第一部分是否能将其缩减。如果能,则会压缩该文件的整个写入;否则不会压缩任何内容。所以,如果数据的第一部分没有被缩减,那么即使数据的其余部分可以大大缩减,写入时也不会被压缩。[4] 这样做是为了防止让磁盘一直等待写入,直到所有要写入的数据传递给 Btrfs 并被压缩后为止。

另外可以改用 compress-force=alg 挂载选项,这会让 Btrfs 跳过对数据第一部分的压缩检查,并尝试对每个文件启用自动压缩。最不济的情况,这会 (稍微) 导致 CPU 占用率无故升高。不过,在多个混合使用系统的经验测试显示,与仅使用 compress=zstd (其也有 10% 的磁盘压缩率) 相比,使用 compress-force=zstd 可以显著提高约 10% 的磁盘压缩率。

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

给现存文件启用压缩,可使用 btrfs filesystem defragment -calg 命令,alg 处可选填为 zliblzozstd。举例来说,要用 zstd 方式给整个文件系统重新压缩,执行下列命令:

# btrfs filesystem defragment -r -v -czstd /

要在新的 Btrfs 分区上安装 Arch Linux 时就启用压缩功能 (充分利用压缩特性),请在 挂载 文件系统时使用 compress 选项:mount -o compress=zstd /dev/sdxY /mnt/。在配置过程中,请在 fstab 中把 compress=zstd 添加到根目录文件系统的挂载选项里。

提示: 通过执行 chattr +c,也可以在不使用 compress 选项的情况下为每个单文件启用压缩属性。对目录执行会使这个目录下新文件自动被压缩。
警告:
  • 如果使用 zstd 参数,使用较旧版本内核或者尚不支持 zstdbtrfs-progs 的系统可能不能读取或修复您的文件系统。
  • GRUB 在 2.04 版本中引入了对 zstd 的支持。使用此后版本时,请通过手动运行 grub-install(需添加适用于机器 BIOS/UEFI 设置的选项参数)确保安装在 MBR/ESP 中的引导加载程序已确实升级,因为这些事情不会自动完成。可参阅 FS#63235

查看压缩类型和压缩比

compsize 软件包能获取一个文件列表 (或一整个 Btrfs 文件系统),并测量出它们使用的压缩类型和其有效压缩比。不过,其给出的未压缩时大小数值不一定能和其他程序 (比如 du) 给出的数值吻合,因为每一文件所占空间范围都会计数一次,即使文件被链接了多次,即使文件的一部分不再被使用 (但其未被垃圾回收)。 -x 选项可让程序运行保持在单一个文件系统上,这在 compsize -x / (检查根目录) 之类的情况下很有用,可以避免程序去尝试访问非 Btrfs 子目录从而导致整个程序运行失败。

子卷

"btrfs 子卷不是 (也不能看作) 块设备,一个子卷可以看作 POSIX 文件名字空间.这个名字空间可以通过子卷上层访问,也可以独立挂载."[5]

每个 btrfs 文件系统都有一个 ID 为 5 的顶层子卷。它可以挂载为 /(默认情况下),或者可以挂载为另一个子卷。子卷可以在文件系统中移动,它们通过其 ID 而不是路径来标识。

参阅下面的链接获得更多信息:

创建子卷

要创建一个子卷:

# btrfs subvolume create /path/to/subvolume

列出子卷列表

要列出当前路径 (path) 下的子卷和它们的 ID:

# btrfs subvolume list -p path

删除子卷

要删除一个子卷:

# btrfs subvolume delete /path/to/subvolume

自 Linux 4.18 起, 用户可以像移除常规目录一样删除一个子卷 (用 rm -r, rmdir 命令)。

挂载子卷

可以使用 subvol=/path/to/subvolumesubvolid=objectid 挂载标志来安装子卷,就像文件系统分区一样。例如,您可以拥有一个名为 subvol_root 的子卷,并将其挂载为 /。通过在文件系统的顶层创建各种子卷,然后将它们挂载到适当的挂载点,可以模仿传统的文件系统分区。 因此,可以使用 #快照 轻松地将文件系统(或其一部分)恢复到先前的状态。

提示: 不使用顶层子卷 (ID=5) 挂载为根目录,可以更方便地修改子卷的布局结构。相反,可考虑创建新的子卷,然后挂载为 /
注意: 引自 btrfs(5) § MOUNT OPTIONS:“大多数挂载选项适用于整个文件系统,并且只有要挂载的第一个子卷的选项才会生效。 这是因为没有实现,未来可能会发生变化。”可参阅 Btrfs Wiki FAQ 以了解哪些挂载参数能够被用于独立的子卷。

参阅 Snapper#Suggested filesystem layout, Btrfs SysadminGuide#Managing SnapshotsBtrfs SysadminGuide#Layout 获得子卷应用的示例。

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

挂载子卷为根挂载点

要使用一个子卷作为根挂载点,请使用 rootflags=subvol=/path/to/subvolume —— 一个 内核参数 指定子卷。在 /etc/fstab 中编辑根挂载点并指定挂载选项 subvol=。或者可以在 /etc/fstab 中用 ID 指定子卷:用 rootflags=subvolid=objectid 作为内核参数并用 subvolid=objectid 作为挂载选项。

改变默认子卷

如果挂载时不指定 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 的形式分配配额组。 但是,如果需要的话,可以使用任意数字创建配额组。

要使用 Qgroup,你首先需要启用它:

# btrfs quota enable path

从此时开始,新创建的子卷将由这些配额组控制。 为了能够为已创建的子卷启用配额,首先正常启用配额,然后使用它们的 subvolume_id 为每个子卷创建一个配额组,再重新扫描它们:

# 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 秒检查点间隔,新数据将在 30 秒内被提交到文件系统。 这可以通过在 /etc/fstab 增加 commit 挂载参数来修改:

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

系统范围的设置也会影响提交间隔。它们包括 /proc/sys/vm/* 下的文件,这超出了本维基文章的范围,因此不再赘述。 它们的内核文档位于 Documentation/sysctl/vm.txt

SSD TRIM

Btrfs 文件系统能够从支持 TRIM 命令的 SSD 驱动器中释放未使用的块。内核从 5.6 版本开始提供了异步丢弃(asynchronous discard)支持,可使用挂载参数 discard=async 启用。已释放的空间范围不会被马上丢弃,它们会被集中起来并在稍后由一个单独的工作线程进行 TRIM,这将能改善提交延迟。

有关启用和使用 TRIM 的更多信息,请参阅 Solid State Drives#TRIM

使用

交换文件

自 Linux 内核版本 5.0 起 Btrfs 提供 交换文件 支持 [7]Swap#建立交换文件 一节中已交代正确初始化交换文件的方法。 Power_management/Suspend_and_hibernate#休眠到 Btrfs 上的交换文件中 一节中则已交代了休眠到交换文件的配置方法。

注意: 对于内核版本 5.0+, Btrfs 有原生但带些许限制的交换文件支持:
警告: Linux 内核 5.0 之前的版本不支持交换文件。在 5.0 之前的内核版本上搭配 Btrfs 使用交换文件可导致文件系统损坏。

显示已使用的/空闲空间

df 这样的用户空间工具可能不会准确的计算剩余空间 (因为并没有分别计算文件和元数据的使用情况) 。推荐使用 btrfs filesystem usage 来查看使用情况。比如说:

# btrfs filesystem usage /
注意: btrfs filesystem usageRAID5/RAID6 设备上可能无法正常工作。

请参阅 [8] 以获取更多信息。

碎片整理

Btrfs 支持通过配置挂载参数 autodefrag 来实现在线的碎片整理,参见 btrfs(5) § MOUNT OPTIONS 。要手动整理你的根目录的话,可以使用:

# btrfs filesystem defragment -r /

使用不带 -r 开关的上述命令将导致仅整理该目录的子卷所拥有的元数据。这允许通过简单地指定路径进行单个文件碎片整理。

对具有 CoW 副本(快照副本或使用cp --reflink或 bcp 创建的文件)进行碎片整理以及使用带压缩算法的 -c 开关进行碎片整理可能会导致生成两个不相关的文件从而增加磁盘使用量。

RAID

Btrfs 提供对 RAID 一类的 #多设备文件系统的原生支持.参阅 the Btrfs wiki page 获得更多信息. Btrfs 管理员手册 提供了技术背景信息.

警告: 奇偶校验 RAID(RAID 5/6)代码中存在多个严重的数据丢失错误。 检查 Btrfs Wiki 的 RAID5/6 页面 (英文) 和 BUG 汇报 (linux-btrfs 邮件列表 (英文)) 以获取更多信息。2020 年 6 月, 有人提出了一个 通俗易懂的现存问题列表 (英文) 和一个 有用的恢复指南 (英文)

检修 (Scrub)

Btrfs Wiki 术语表中写到,Scrub 是一种 "在线文件系统检查工具"。它能读取文件系统中的文件和元数据,并使用校验值和 RAID 存储上的镜像区分并修复损坏的数据。

警告: 运行 scrub 会阻止系统待机, 详见 这个讨论

手动启动

启动一个(后台运行的)包含 / 目录的文件系统在线检查任务:

# btrfs scrub start /

检查该任务的运行状态:

# btrfs scrub status /

通过服务或者定时器启动

btrfs-progs 软件包带有 btrfs-scrub@.timer 系统单元,用来每月运行 scrub 命令。通过添加挂载点的参数来启用它,例如btrfs-scrub@-.timer (/) 或者 btrfs-scrub@home.timer (/home).

也可以通过启动 btrfs-scrub@.service 来手动运行 scrub (使用同样的挂载点参数),相较 (以 root 用户身份运行) btrfs scrub,这么做的优点是会记录在 Systemd 日志中。

数据平衡 (Balance)

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

在单设备文件系统上,余额对于(临时)减少分配但未使用(元)数据块的数量也是有用的。有时候这对于解决 "filesystem full" 故障 来说也是必须的。

# btrfs balance start /
# btrfs balance status /

快照

"快照是和特定子卷共享文件和元数据的特殊子卷, 利用了 btrfs 的写时复制特性." 详见 Btrfs Wiki SysadminGuide#Snapshots.

要创建一个快照:

# btrfs subvolume snapshot source [dest/]name

source为要创建快照的对象,[dest/]name为快照安放路径。

加入 -r 参数可以创建一个只读快照. 为只读快照创建一个快照可以获得一个只读快照的可写入版本.

注意: 快照不是递归包含的,这意味着子卷内的子卷在快照里是空目录。

发送和接收

可以通过 send 命令发送一个快照,通常会与 btrfs 中的 receive 组成管道.例如将快照 /root_backup (也许是/的备份) 发送到 /backup:

 # btrfs send /root_backup | btrfs receive /backup

只能发送只读快照,上面的命令在将子卷复制到外部设备 (例如备份驱动器) 时会很有用.

也可以只发送两个快照间发生变化的部分,例如如果你已经发送了快照 root_backup ,然后又建立了一个新的只读快照 root_backup_new ,可以这样完成增量发送:

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

现在你 /backup 的快照会是 root_backup_new.

参阅 Btrfs Wiki 上关于增量备份的页面 (英文) 获得更多信息 (例如使用工具自动化这一过程)。

去重

使用写时复制,Btrfs 能够复制文件或整个子卷而无需实际复制数据。但是,无论何时更改文件,都会创建一个新的“真正的”副本。重复数据删除更进一步,通过主动识别共享公共序列的数据块并将它们组合到具有相同写时复制语义的范围内。

专用于 Btrfs 分区去重的工具包括 duperemovebedupAURbtrfs-dedup。人们可能还希望仅使用基于文件的级别对数据进行重复数据删除,比如 rmlintjdupesAUR 或者 dduper-gitAUR。有关这些程序的可用功能的概述和其他信息,请参阅 上游 Wiki 条目 (英文)

此外,Btrfs开发人员正致力于带内(也称为同步或内联)重复数据删除,这意味着在将新数据写入文件系统时完成重复数据删除。目前,它仍然是一个在 out-of-tree 开发的实验。愿意测试新功能的用户可以阅读相关的内核 Wiki 页 (英文)

已知问题

一些在尝试之前应该知道的限制。

加密

Btrfs 目前还没有内建的加密支持,但未来可能加入此功能。可以在运行mkfs.btrfs前加密分区,参阅Dm-crypt with LUKS.

(如果已经创建了文件系统,可以使用EncFSTrueCrypt,但是这样会无法使用 btrfs 的一些功能。)

检查 btrfs 文件系统问题

btrfs check 工具目前有一些已知问题,在继续深入阅读了解之前,您不应该直接运行它, 参见 #检查 Btrfs 文件系统 小节。

提示和技巧

无分区 Btrfs 磁盘

警告: 大多数用户不希望这种类型的设置,应该在常规分区上安装 Btrfs。 此外,GRUB 强烈建议不要安装到无分区磁盘。请考虑为 mkfs.btrfs 使用 --alloc-start 参数以留出更大空间给 GRUB。

Btrfs 能应用到整个设备上,替代 MBRGPT 分区表,但是并不要求一定这么做,最简单的方法是 在一个已存在的分区上创建 Btrfs 文件系统。 如果选择用 Btrfs 替代分区表, 可以用 #子卷 模拟不同的分区。下列是在单个无分区设备上使用 Btrfs 文件系统的限制:

  • 不能在同一磁盘上的不同分区上放置其它的 文件系统
  • 如果使用 5.0 之前版本的 Linux 内核,则不能使用 交换区,因为 Btrfs 在 5.0 前不支持 交换文件,并且也无处创建 交换分区
  • 不能使用 UEFI 启动。

运行下面的命令把整个设备的分区表替换成 Btrfs:

# mkfs.btrfs /dev/sdX

如果设备上存在分区表,则需要使用:

# mkfs.btrfs -f /dev/sdX

例如 /dev/sda 而不是 /dev/sda1。后一种形式会格式化现有的分区而不是替换掉原有的分区表。由于根分区是 Btrfs 文件系统,请确保已将 btrfs 编译进内核, 或者将 btrfs 放入 mkinitcpio.conf#MODULES 中并且 重新生成 initramfs

像使用普通的 MBR 分区表存储设备一样安装 启动管理器, 参考 Syslinux#Manual installGRUB/Tips and tricks#Install to partition or partitionless disk。 如果你的内核因为 Failed to mount /sysroot. 错误无法启动, 请在 /etc/default/grub 里添加 GRUB_PRELOAD_MODULES="btrfs" 并生成 GRUB 配置文件 (GRUB#Generate the main configuration file)。

从 Ext3/4 转换

警告: 到 2015 年中后期,Btrfs 的邮件列表中报告了多起转换失败的案例。尽管近期的更新可能有所修复,但还是建议谨慎使用。在开始之前请确定您有可用的备份并且愿意承担丢失数据的风险。 详见 Btrfs Wiki:从 Ext3 文件系统转换 (英文)
警告: 5.6.1 及之前版本的 btrfs-progs 有一个 Bug,它会导致生成的 Btrfs 文件系统的最后一块组 (last block group) 含有大小错误。得益于 这个 commit,这个 Bug 已经在 5.7 版本中修复。请在 5.7-1 及以上版本的 btrfs-progs 上使用 brtfs-convert 功能。

从安装 CD 启动,然后转化分区:

# btrfs-convert /dev/partition

挂载转换后的分区并修改 /etc/fstab 文件,指定分区类型 (type 为 btrfs,并且 fs_passno[最后一列] 要修改为0,因为 Btrfs 在启动时并不进行磁盘检查)。 还要注意的是分区的 UUID 将有改变,所以使用 UUID (指定分区) 时,请更新 fstab 中相应的条目。 chroot 到系统并重建 GRUB 条目(如果对此过程不熟悉,参考从现有 Linux 系统安装GRUB 中的相应内容)。 如果正在转换根目录,还需要在 chroot 环境中重建初始化内存盘 (mkinitcpio -p linux)。 如果 GRUB 不能启动 (例如有 'unknown filesystem' 错误),则需要重新安装 (grub-install /dev/partition) 并重新生成配置文件 (grub-mkconfig -o /boot/grub/grub.cfg)。

注意: 如果转换过程中有任何异样,不管是无法挂载新转换的 Btrfs 文件系统或是无法往其中写入数据,只要备份子卷 /ext2_saved 还在,就可以进行回滚。请使用 btrfs-convert -r /dev/partition 命令进行回滚,这将会丢弃任何对新转换 Btrfs 文件系统的更改。

确认没有问题后,通过删除 ext2_saved 备份子卷完成转换的最后一步。请注意,如果没了它 (备份子卷),你将没办法还原回 ext3/4 文件系统。

# btrfs subvolume delete /ext2_saved

最后通过 Balance 回收空间。

校验和 (Checksum) 硬件加速

CRC32 是英特尔 (Intel) SSE4.2 中的新指令。要验证 Btrfs 校验和是否有硬件加速:

# dmesg | grep crc32c
Btrfs loaded, crc32c=crc32c-intel

如果你看到的是 crc32c=crc32c-generic,则很有可能是因为您根分区是 Btrfs,并且您须要之后将 crc32c-intel 编译进内核中才能使其正常生效。单纯将 crc32c-intel 放入 mkinitcpio.conf不会 生效的。

损坏恢复

警告: btrfs check 工具有一些已知问题,参见 #检查 Btrfs 文件系统 小节。

btrfs-check 不能在一个已挂载的文件系统上工作。为了能够在不从 Live USB 启动的情况下使用 btrfs-check,需要将其添加到初始内存盘:

/etc/mkinitcpio.conf
BINARIES=("/usr/bin/btrfs")

然后 重新生成 initramfs

之后如果启动时出现问题,则可以使用该实用程序进行修复。

注意: 如果 fsck 进程必须使空间缓存 (和/或其他缓存?) 无效 (invalidate cache),那么随后的引导会挂起一段时间,这是正常的(进程可能会给出关于 btrfs-transaction 挂起的控制台消息)。系统应该在一段时间后从中恢复正常。

查阅 Btrfs Wiki 的 Btrfsck 页 以获取更多信息。

引导进入快照

要引导进入快照,因为快照可以像子卷那样被挂载,所以请像挂载子卷为根分区那样进行同样的流程 (已交代于#挂载子卷为根挂载点的一段中)。

如果使用 GRUB,则可以在 grub-btrfsgrub-btrfs-gitAUR 的帮助下,在重新生成配置文件时使用 Btrfs 快照自动填充启动菜单。

搭配 systemd-nspawn 使用 Btrfs 子卷

可查阅 Systemd-nspawn#Use Btrfs subvolume as container rootSystemd-nspawn#Use temporary Btrfs snapshot of container 等文章。

疑难解答

请查阅 Btrfs 常见问答集(英文) 以获得排除一般问题的信息。

GRUB

分区偏移

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

GRUB 2 可以引导启动 Btrfs 分区,但是因为模块比其它文件系统大,grub-install 生成的 core.img 文件超过了 MBR 与第一个分区之间的空间大小 (63 扇区/31.5KiB)。最新版的 fdiskgdisk 等磁盘工具会通过第一个分区前空出 1-2MiB 的空间来避免此问题。

Missing root

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Suggests editing a non-configuration file manually. (Discuss in Talk:Btrfs#Should not suggest to edit files in /usr/share)

Users experiencing the following: error no such device: root when booting from a RAID style setup then edit /usr/share/grub/grub-mkconfig_lib and remove both quotes from the line echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}". Regenerate the config for grub and the system should boot without an error.

挂载超时

有时(尤其在大型 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 错误

截至 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.

一种解决办法是,从 HOOKS 中将 btrfs 移入 MODULES 中,然后通过 mkinitcpio -p linux 命令重新生成 initramfs 并重新启动。

请查阅 原论坛讨论FS#42884 获得更多的讨论内容和信息。

另外,如果在挂载 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 列表中。

检查 Btrfs 文件系统

警告: Btrfs(特别是 btrfs check 命令工具)仍处在大开发阶段,强烈建议在加上 --repair 参数运行 btrfs check 前先做一个备份,并提前阅读 Btrfsck 文档(英文)

btrfs check 可以检查并修复一个未挂载的 Btrfs 文件系统。但是由于它尚未开发完成,它并不能修复某些错误(即使这些错误没有导致无法挂载的情况发生)。

另请参阅