Btrfs
引自 Btrfs 文档介绍:
- BTRFS 是一种现代的写时复制(COW)Linux 文件系统,致力于实现一些高级功能,同时着重于容错性、修复性以及易于管理性。
准备工作[编辑 | 编辑源代码]
请安装基础操作所必须的 btrfs-progs包 软件包以使用用户空间工具。
如果需要从 Btrfs 文件系统引导启动(比如说内核和初始内存文件系统(initramfs)驻留在 Btrfs 分区上),请检查启动引导器是否支持 Btrfs。
创建文件系统[编辑 | 编辑源代码]
下文展示了如何创建一个新的 Btrfs 文件系统。要将一个 Ext3/4 分区转换为 Btrfs,请参考 #从 Ext3/4 转换。要使用无分区的配置,请参考 #无分区 Btrfs 磁盘。
查阅 mkfs.btrfs(8) 以获取更多信息。
单一设备上的文件系统[编辑 | 编辑源代码]
要在分区 /dev/partition
上创建一个 Btrfs 文件系统,执行:
# mkfs.btrfs -L 自定义标签 /dev/分区名
Btrfs 用于元数据的默认节点大小 (nodesize) 为 16 KiB,而用于数据的默认扇区大小 (sectorsize) 等于页面大小 (page size) 并会自动检测。 要对元数据使用较大的节点大小 (必须为扇区大小的倍数,最大允许 64 KiB),请通过 -n
选项开关指定 nodesize
的值。如下例所示,要使用 32 KiB 大小的块:
# mkfs.btrfs -L 自定义标签 -n 32k /dev/分区名
多设备文件系统[编辑 | 编辑源代码]
- Btrfs 的 RAID 5 和 RAID 6 模式存在致命缺陷,除非用来做数据丢失测试,否则不应当用于任何场景。这里有已知问题和部分解决方法的列表。 查阅 btrfs(5) § RAID56 STATUS AND RECOMMENDED PRACTICES 以获取最新动态。
- 默认情况下,systemd 会为
/var/log/journal
目录禁用写时复制 (CoW),这会导致在 RAID 1 上损坏数据(参见#停用 CoW)。要避免这种情况,请在/etc/tmpfiles.d/journal-nocow.conf
创建一个空文件,以此覆盖掉/usr/lib/tmpfiles.d/journal-nocow.conf
(参阅 tmpfiles.d(5) § CONFIGURATION DIRECTORIES AND PRECEDENCE)。
多个设备可以用来创建一组 RAID。支持的 RAID 级别有 RAID 0、RAID 1、RAID 10、RAID 5 和 RAID 6。从 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
钩子或 btrfs
钩子才能在一个池中使用多个 Btrfs 设备。查阅 Mkinitcpio#常用钩子以获取更多信息。
一旦创建好了文件系统,建议使用下面的命令扫描多设备Btrfs文件系统并注册它们,这样在挂载多设备文件系统时就仅需指定其中的一个设备:
# btrfs device scan
- 可以稍后再将设备添加到多设备文件系统中。详情请参见 Btrfs wiki 文章。
- 多个设备可以大小各异。但是,如果在 RAID 配置中一个硬盘的大小比其他的都大,那么它多出的空间将不会被使用。
- 有些 引导加载程序 不支持多设备文件系统,比如 Syslinux。
- Btrfs 不会自动从速度最快的设备读取,因此混合使用不同类型的磁盘会导致性能表现不稳定。详情请参阅 Stack Overflow 上的这个回答。
#RAID 小节中有关于维护多设备上的 Btrfs 文件系统的一些建议。
Profiles[编辑 | 编辑源代码]
Btrfs使用profiles这个概念来配置RAID的镜像、奇偶校验和条带属性,在标准的RAID术语中叫做RAID 级别。在同一个Btrfs文件系统中,元数据的Profiles(mkfs.btrfs(8)的-m
选项)和数据的Profiles(mkfs.btrfs(8)的-d
选项)可以不一样。
一些重要的Profiles:
- single
- 没有镜像、条带和奇偶校验,让多个设备映射到单个文件系统中,在mdadm术语中被叫做
LINEAR
。 - raid0
- 没有镜像、条带和奇偶校验,但允许并行访问设备,只是不像传统的mdadm RAID那样要求设备大小相同。
- raid1
- 镜像,没有条带和奇偶校验,允许从一个设备失效的情况下恢复访问。
配置文件系统[编辑 | 编辑源代码]
写时复制 (CoW)[编辑 | 编辑源代码]
默认情况下 Btrfs 总是对所有文件使用写时复制 (CoW)。写入不会就地覆盖数据;相反,数据块在被复制和修改后会写入到新的位置,元数据也会更新以指向新的位置。请参阅 Btrfs 系统管理指南相关章节以获取实现细节以及它的优点和缺点。
停用 CoW[编辑 | 编辑源代码]
nodatacow
文件。与 RAID1 结合使用时,断电或其他导致损坏的原因可能会使数据失去同步。要对某个子卷上的新文件停用写时复制,使用 nodatacow
挂载选项。这只会影响新创建的文件,写时复制仍然会在已存在的文件上生效。nodatacow
参数同样会禁用压缩。参阅 btrfs(5) 以了解细节。
nodatacow
参数挂载,而其他的使用 datacow
参数挂载。第一个被挂载子卷的挂载参数将会应用于其他所有子卷。“要单文件或目录禁用写时复制特性,请使用下面的命令:
$ chattr +C /目录/文件
这会为这个文件的单个引用停用写时复制,如果这个文件不只有一个引用,比如文件有多个克隆或轻量克隆(clones / lightweight clones)或者在文件系统快照中,写时复制依然生效。注意自coreutils包 9.0版本起,cp
默认使用轻量复制,更多细节参见cp(1)。
- “在 Btrfs 上,'
C
' 标志应该被设置在新建的或者是空白的文件,如果被设置在已有数据的文件,当块分配给该文件时,文件将不确定是否完全稳定。如果 'C
' 标志被设置给一个目录,将不会影响目前的目录,但在该目录创建的新文件将具有No_COW
属性。”
$ 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需要保证这个过程中目标文件不会被使用,同时注意下面描述的
mv
或 cp
在没有--reflink=never
时将不会生效。对快照的影响[编辑 | 编辑源代码]
如果一个文件禁用了写时复制(NOCOW)并创建了一个快照,在快照后,第一次在该文件的块写入将会是一个COW操作,因为快照锁定了旧文件的块来确保内容正确。但文件依然保留了NOCOW属性,任何后续写入操作依然在本次快照后产生的相同文件块中进行,直到产生下一次快照。
频繁快照会降低NOCOW的效果,因为在每次快照后的第一次写入都需要COW。要避免这种情况,可以把所有NOCOW文件放在一个单独的子卷中并避免对该子卷进行快照操作。
压缩[编辑 | 编辑源代码]
Btrfs 支持透明和自动压缩。这就减小了文件的大小,通过减少文件写入增幅来显著延长闪存介质(flash-baesd media)的寿命 [1][2][3]。在某些特定的场景下(比如单线程、重负荷的文件 I/O))还提高了性能。尽管在其他的场景下(比如多线程和/或大文件 I/O 高强度 CPU 任务)还是明显影响了性能。通常使用更快的压缩算法,比如 zstd 和 lzo 可以获得更好的性能,这个性能测试提供了详细的对比。
LZO的压缩等级是固定的,而ZLIB和ZSTD有从1到9(ZLIB)或15(ZSTD)的压缩等级,等级越高压缩率越大,参见btrfs(5) § COMPRESSION。改变压缩等级将直接影响CPU和I/0吞吐,建议在改变压缩等级前后进行检查或性能测试。
compress=alg[:level]
挂载选项可自动考虑为每个文件启用压缩,其中的 alg
处可以选填为 zlib
, lzo
, zstd
, 或者 no
(即不压缩)。由此,Btrfs 将检查压缩数据的第一部分是否能将其缩减。如果能,则会压缩该文件的整个写入;否则不会压缩任何内容。所以,如果数据的第一部分没有被缩减,那么即使数据的其余部分可以大大缩减,写入时也不会被压缩。[4]这样做是为了防止让磁盘一直等待写入,直到所有要写入的数据传递给 Btrfs 并被压缩后为止。
另外可以改用 compress-force=alg[:level]
挂载选项,这会让 Btrfs 跳过对数据第一部分的压缩检查,并尝试对每个文件启用自动压缩。最不济的情况,这会 (稍微) 导致 CPU 占用率无故升高。不过,在多个混合使用系统的试验测试显示,与仅使用 compress=zstd
(其也有 10% 的磁盘压缩率) 相比,使用 compress-force=zstd
可以显著提高约 10% 的磁盘压缩率。不过,请注意官方Btrfs指导手册不推荐使用强制压缩。
只有在加入挂载选项后创建或修改的文件才会被压缩。
给现存文件启用压缩,可使用 btrfs filesystem defragment -calg
命令,alg
处可选填为 zlib
,lzo
或 zstd
。举例来说,要用 zstd包 方式给整个文件系统重新压缩,执行下列命令:
# btrfs filesystem defragment -r -v -czstd /
cp
或 bcp 创建的文件)进行碎片整理以及使用带压缩算法的 -c
开关进行碎片整理可能会导致生成两个不相关的文件从而大幅增加磁盘使用量。要在新的 Btrfs 分区上安装 Arch Linux 时就启用压缩功能,请在挂载文件系统时使用 compress
选项:mount -o compress=zstd /dev/sdxY /mnt/
。在配置过程中,请在 fstab 中把 compress=zstd
添加到根目录文件系统的挂载选项里。
chattr +c
或btrfs property set file compression alg
,也可以在不使用 compress
选项的情况下为每个单文件启用压缩属性。第一个命令适用于传统的文件属性(继承自ext2文件系统,不太灵活),因此压缩算法只能使用默认的zlib
。第二个命令可以为压缩的文件指定压缩算法(但需要注意指定压缩级别目前还没有实现)。对目录执行会使这个目录下新文件自动被压缩。- 如果使用
zstd
参数,使用较旧版本内核或者尚不支持zstd
的 btrfs-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文件系统必须先挂载。子卷名通过最后一个参数设置。
# btrfs subvolume create /path/to/subvolume
--parents
选项自动创建对应的文件目录。列出子卷列表[编辑 | 编辑源代码]
要列出当前路径 (path
) 下的子卷和它们的 ID:
# btrfs subvolume list -p path
删除子卷[编辑 | 编辑源代码]
要删除一个子卷:
# btrfs subvolume delete /path/to/subvolume
用户也可以像移除常规目录一样删除一个子卷 (用 rm -r
, rmdir
命令)。
挂载子卷[编辑 | 编辑源代码]
可以使用 subvol=/path/to/subvolume
或 subvolid=objectid
挂载标志来安装子卷,就像文件系统分区一样。例如,您可以拥有一个名为 subvol_root
的子卷,并将其挂载为 /
。通过在文件系统的顶层创建各种子卷,然后将它们挂载到适当的挂载点,可以模仿传统的文件系统分区。建议使用subvol=/path/to/subvolume
而不是子卷ID(subvolid)挂载,因为在恢复#快照时子卷ID可能会变化,需要修改挂载配置。
/
。- “大多数挂载选项适用于整个文件系统,并且只有要挂载的第一个子卷的选项才会生效。 这是因为没有实现,未来可能会发生变化。”
可参阅 Btrfs Wiki FAQ 以了解哪些挂载参数能够被用于独立的子卷。
参阅 Snapper#推荐文件系统布局, Btrfs SysadminGuide#Managing Snapshots 和 Btrfs SysadminGuide#Layout 获得子卷应用的示例。
有关 Btrfs 特定的挂载选项的完整列表,请参阅 btrfs(5)。
挂载子卷为根挂载点[编辑 | 编辑源代码]
要使用一个子卷作为根挂载点,可以通过设置默认子卷或指定 rootflags=subvol=/path/to/subvolume
内核参数。在 /etc/fstab
中编辑根挂载点并指定挂载选项 subvol=
。或者可以在 /etc/fstab
中用 ID 指定子卷:用 rootflags=subvolid=objectid
作为内核参数并用 subvolid=objectid
作为挂载选项。建议使用subvol=/path/to/subvolume
而不是子卷ID,因为在恢复#快照时子卷ID可能会变化,需要修改挂载配置,否则系统可能不会正确启动。
改变默认子卷[编辑 | 编辑源代码]
如果挂载时不指定 subvol=
选项便会挂载默认子卷。要改变默认子卷,执行:
# btrfs subvolume set-default subvolume-id /
subvolume-id 可以通过#列出子卷列表获得。
通过 btrfs subvolume set-default
修改默认子卷将会导致文件系统的最顶层无法访问,除非使用 subvol=/
或者 subvolid=5
挂载参数。[6]
配额[编辑 | 编辑源代码]
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/*
下的文件,这超出了本文的范围,因此不再赘述。 它们的内核文档位于 https://docs.kernel.org/admin-guide/sysctl/vm.html 。
固态硬盘 TRIM[编辑 | 编辑源代码]
Btrfs 文件系统能够从支持 TRIM 命令的 SSD 驱动器中释放未使用的块。可使用挂载参数 discard=async
启用异步丢弃(asynchronous discard)支持,linux包 6.2 版本已经默认启用该功能。已释放的空间范围不会被马上丢弃,它们会被集中起来并在稍后由一个单独的工作线程进行 TRIM,这将能改善提交延迟。
异步丢弃可以安全地同定期TRIM使用[7]。
有关启用和使用 TRIM 的更多信息,请参阅固态硬盘#TRIM。
使用[编辑 | 编辑源代码]
交换文件[编辑 | 编辑源代码]
创建交换文件的正确方法是首先创建一个非快照子卷以存储交换文件,
# btrfs subvolume create /swap
创建交换文件:
# btrfs filesystem mkswapfile --size 4g --uuid clear /swap/swapfile
如果未指定 --size
选项,交换文件默认大小为2 GiB。
启用交换文件:
# swapon /swap/swapfile
最后编辑fstab,添加交换文件的配置:
/etc/fstab
/swap/swapfile none swap defaults 0 0
更多信息参见Fstab#用法
要使用休眠功能,除了配置交换文件外,你还需要完成电源管理/挂起与休眠中描述的额外步骤。
显示已使用的/空闲空间[编辑 | 编辑源代码]
像 df(1) 这样的用户空间工具可能不会准确的计算剩余空间 (因为并没有分别计算文件和元数据的使用情况) 。推荐使用 btrfs filesystem usage
来查看使用情况。比如说:
# btrfs filesystem usage /
btrfs filesystem usage
在 RAID5/RAID6
设备上可能无法正常工作。或者使用btrfs filesystem df
在非root权限下快速检查已分配空间的使用情况:
$ btrfs filesystem df /
请参阅 [8] 以获取更多信息。
像du(1) 和 ncdu(1) 这类分析文件系统子集空间使用的工具同样受到影响,因为其没有考虑reflink,快照和压缩。可以考虑使用btduAUR和compsize这类可识别btrfs特性的工具。
碎片整理[编辑 | 编辑源代码]
Btrfs 支持通过配置挂载参数 autodefrag
来实现在线的碎片整理,参见 btrfs(5) § MOUNT OPTIONS 。要手动整理你的根目录的话,可以使用:
# btrfs filesystem defragment -r /
使用不带 -r
开关的上述命令将导致仅整理该目录的子卷所拥有的元数据。这允许通过简单地指定路径进行单个文件碎片整理。
cp
或 bcp 创建的文件)进行碎片整理以及使用带压缩算法的 -c
开关进行碎片整理可能会导致生成两个不相关的文件从而大幅增加磁盘使用量。RAID[编辑 | 编辑源代码]
Btrfs 提供对 RAID 一类的 #多设备文件系统的原生支持。自修复冗余阵列和在线数据在线平衡是使btrfs RAID 与mdadm区分开来的重要特性。参阅 the Btrfs wiki page 获得更多信息。Btrfs 管理员手册提供了一些额外技术背景信息。
检修 (Scrub)[编辑 | 编辑源代码]
Btrfs Wiki 术语表中写到,Scrub 是一种"在线文件系统检查工具"。它能读取文件系统中的文件和元数据,并使用校验值和 RAID 存储上的镜像区分并修复损坏的数据。
手动启动[编辑 | 编辑源代码]
启动一个(后台运行的)包含 /
目录的文件系统在线检查任务:
# btrfs scrub start /
检查该任务的运行状态:
# 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 (使用同样的转移后路径),相较 (以 root 用户身份运行) btrfs scrub
,这么做的优点是输出内容会记录在 Systemd 日志中。
数据平衡 (Balance)[编辑 | 编辑源代码]
"Balance 将会通过分配器再次传递文件系统中的所有数据。它主要用于在添加或删除设备时跨设备重新平衡文件系统中的数据。如果设备出现故障,余额将为冗余 RAID 级别重新生成缺失的副本。"[9]。参阅上游的 FAQ.
在单设备文件系统上,数据平衡对于(临时)减少分配但未使用(元)数据块的数量也是有用的。有时候这对于解决 "filesystem full" 故障来说也是必须的。
# btrfs balance start --bg / # btrfs balance status /
快照[编辑 | 编辑源代码]
"快照是和其它子卷共享数据和元数据的简单子卷, 利用了 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合并到同一个区(extend)内。
专用于 Btrfs 分区去重的工具包括 duperemove包和bees包。也许你还希望基于文件的级别对数据进行重复数据删除,比如 rmlint包、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 目前还没有内建的加密支持,但未来可能加入此功能。可以在运行mkfs.btrfs
前加密分区,参阅 Dm-crypt/加密整个系统。另一个选择是栈式文件系统加密。
检查 btrfs 文件系统问题[编辑 | 编辑源代码]
btrfs check
工具目前有一些已知问题,在继续深入阅读了解之前,您不应该直接运行它, 参见 #检查 Btrfs 文件系统小节。
提示和技巧[编辑 | 编辑源代码]
无分区 Btrfs 磁盘[编辑 | 编辑源代码]
Btrfs 能占用整个存储设备,使用子卷模拟分区表来替代 MBR 或 GPT 分区表。虽然无分区磁盘不需要使用其它方法创建分区,然后在一个分区上创建 Btrfs 文件系统,但在单个磁盘上使用无分区配置存在一些限制:
运行下面的命令把整个设备的分区表替换成 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 转换[编辑 | 编辑源代码]
从安装 CD 启动,然后转化分区:
# btrfs-convert /dev/partition
挂载转换后的分区并修改 /etc/fstab
文件,指定分区类型 (type 为 btrfs,并且 fs_passno[最后一列] 要修改为0,因为 Btrfs 在启动时并不进行磁盘检查)。
还要注意的是分区的 UUID 将有改变,所以使用 UUID (指定分区) 时,请更新 fstab 中相应的条目。 chroot
到系统并重建你的引导加载器(如果对此过程不熟悉,参考从现有 Linux 发行版安装 Arch Linux )。 如果转换了根文件系统,还需要在 chroot 环境中重建初始化内存盘 (mkinitcpio -p linux
)以确保系统正确启动。
/ext2_saved
还在,就可以进行回滚。请使用 btrfs-convert -r /dev/partition
命令进行回滚,这将会丢弃任何对新转换 Btrfs 文件系统的更改。确认没有问题后,通过删除 ext2_saved
备份子卷完成转换的最后一步。请注意,如果没了它 (备份子卷),你将没办法还原回 ext3/4 文件系统。
# btrfs subvolume delete /ext2_saved
最后通过数据平衡回收空间。
别忘了先前安装的一些应用需要额外设置来适配Btrfs。
损坏恢复[编辑 | 编辑源代码]
btrfs check
工具有一些已知问题,参见 #检查 Btrfs 文件系统 小节。btrfs-check 不能在一个已挂载的文件系统上工作。为了能够在不从 Live USB 启动的情况下使用 btrfs-check,需要将其添加到初始内存盘:
/etc/mkinitcpio.conf
BINARIES=(btrfs)
之后如果启动时出现问题,则可以使用该实用程序进行修复。
查阅 btrfs-check(8) 以获取更多信息。
引导进入快照[编辑 | 编辑源代码]
要引导进入快照,因为快照可以像子卷那样被挂载,所以请像挂载子卷为根分区那样进行同样的流程 (已交代于#挂载子卷为根挂载点的一段中)。
如果使用 GRUB,则可以在 grub-btrfs包 或 grub-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 send
和 btrfs receive
将备份增量发送到外置设备上。 参考它们的文档来查看实现,功能和需求的不同。
- btrbk — Btrfs子卷的快照和远程备份工具
- snap-sync — 使用Snapper快照并备份到外置设备或远程机器
- snapsync — Snapper的同步工具
下列工具运行备份snapper快照到非Btrfs文件系统。
- snapborg — 一个类似borgmatic的工具,将snapper快照与borg包整合起来
自动快照[编辑 | 编辑源代码]
要管理并自动创建快照,你可以使用像Snapper,Timeshift或Yabsnap这样的快照管理器。
疑难解答[编辑 | 编辑源代码]
请查阅 Btrfs 疑难解答和Btrfs 常见问答集(英文)以获得排除一般问题的信息。
GRUB[编辑 | 编辑源代码]
分区偏移[编辑 | 编辑源代码]
core.img
嵌入到已分区磁盘上时,可能会发生偏移问题。这意味着可以将 GRUB 的 corg.img
直接嵌入到无分区磁盘 (例如 /dev/sdX
) 上的 Btrfs 存储池中。GRUB 可以引导启动 Btrfs 分区,但是因为模块可能会比其它文件系统大,grub-install
生成的 core.img
文件超过了 MBR 与第一个分区之间的空间大小 (63 扇区/31.5KiB)。最新版的 fdisk
和 gdisk
等磁盘工具会通过第一个分区前空出 1-2MiB 的空间来避免此问题。
根丢失[编辑 | 编辑源代码]
当从一个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 错误[编辑 | 编辑源代码]
截至 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 文件系统[编辑 | 编辑源代码]
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来替代。
另请参阅[编辑 | 编辑源代码]
- 官方网站
- 性能相关
- 杂项
- 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