Linux上的新一代文件系统-Btrfs使用

Linux上的新一代文件系统-Btrfs使用

准备工做

Btrfs 支持已经包含在linuxlinux-lts的内核中。php

要使用一些用户空间工具的话,须要安装 不在 base 包组中的并且基础操做必须的 btrfs-progs 软件包。html

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

建立文件系统

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

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

单一设备上的文件系统

在分区 /dev/partition 上建立一个 Btrfs 文件系统:github

# mkfs.btrfs -L mylabel /dev/partition

Btrfs 的默认块大小为 16KB。 要使用更大的 blocksize 数据/元数据的话,能够经过指定 -n 来修改 nodesize,正如本例所示的设置为 16KB:算法

# mkfs.btrfs -L mylabel -n 16k /dev/partition

多设备文件系统

Warning: Btrfs 的 RAID 5 和 RAID 6 模式存在致命缺陷, 不该当用于任何场景,除非用来作丢失数据的测试。 查阅 the Btrfs page on RAID5 and RAID6 以获取最新动态。

多个设备能够用来建立一组 RAID。支持的RAID级别有 RAID 0,RAID 1,RAID 10,RAID 5 和 RAID 6。数据和元数据的 RAID 等级能够独立地用 -d-m 参数指定。默认状况下元数据使用镜像 (RAID1),而数据则会被条带化 (RAID0)。参阅 Btrfs Wiki:在多个设备上使用 btrfs 或查阅 mkfs.btrfs 的手册页得到更多信息.shell

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

要将多个 Btrfs 设备做为一个池使用的话,你须要将 udev 钩子或者 btrfs 钩子加入到 /etc/mkinitcpio.conf 中。查阅 Mkinitcpio (简体中文)#经常使用钩子以获取更多信息。缓存

Note:
  • 磁盘阵列中的各个磁盘大小不同可能会致使不能使用全部磁盘的完整空间。为了充分利用全部磁盘的容量,使用 -d single 而不是 -d raid0 -m raid1 (元数据镜像,数据非镜像且非条带化)
  • 挂载一个这样的文件系统可能会致使除了对应的 .device 的全部任务卡死且 Systemd 可能由于没法正确处理多设备 btrfs 文件系统上的每个设备而不能正常启动,详见这个 BUG 报告
  • 有些启动加载器不支持多设备文件系统,好比 Syslinux

RAID 中有关于维护多设备上的 btrfs 文件系统的一些建议.多线程

配置文件系统

写时复制 (CoW)

默认状况下 btrfs 对全部文件使用 写时复制 (CoW)。参阅the Btrfs Sysadmin Guide section 以获取实现细节以及它的优势和缺点。

停用 CoW

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

Note: 来自 Btrfs Wiki Mount options: within a single file system, it is not possible to mount some subvolumes with nodatacow and others with datacow. The mount option of the first mounted subvolume applies to any other subvolumes.
Note: 根据 Btrfs Wiki Mount options: 在单个文件系统中,没法使用 nodatacow 参数挂载某些子卷,而其余的使用 datacow 参数。第一个被挂载子卷的挂载参数将会应用于其余全部子卷。

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

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

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

Note: 来自 chattr 的手册页:在btrfs上,'C' 标志应该被设置在新建的或者是空白的文件/目录,若是被设置在已有数据的文件,当块分配给该文件时,文件将不肯定是否彻底稳定。若是'C' 标志被设置给一个目录,将不会影响目前的目录,但在该目录建立的新文件将具备No_COW属性。
Tip: 能够用下面的方法为已存在的文件或目录停用写时复制:
$ 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支持透明压缩,这意味着分区里的每一个文件都被自动压缩。这不单减少了文件的大小,在某些特定的场景下(好比单线程、重文件 I/O)还提升了性能,尽管在其余的场景下(好比多线程和/或具备大文件 I/O 的 CPU 密集型任务)显著得影响了性能。使用更快的压缩算法好比 zstdlzo 一般能够得到更好的性能,这个性能测试 提供了详细的对比。

压缩能够经过使用挂载参数 compress 来启用,它的可选值包括 zliblzozstd 或者是 no (不启用压缩)。只有在加入挂载选项后建立或修改的文件才会被压缩。

不过也能够在安装之后经过 btrfs filesystem defragment -calg (也可使用其它压缩算法,例如 zlib / lzo) 压缩一个分区 (例如从 ext3/4 转换之后的文件系统).

要将整个文件系统经过 zstd 从新压缩,运行下面的命令:

# btrfs filesystem defragment -r -v -czstd /

在一个新的 btrfs 分区上安装 Arch Linux 时,要充分利用压缩特性,最好安装时就启用压缩功能。在File systems 时使用 compress 参数: mount -o compress=lzo /dev/sdxY /mnt/.在 时把 compress=lzo 添加到 fstab 中的根目录中的选项上。

Tip: 经过 chattr +c ,也能够在不使用 compress 选项的状况下为单个文件启用压缩属性.对目录启用会使这个目录下新文件自动压缩.
Warning:
  • 若是你使用 zstd 这个参数的话,使用没有 zstd 支持的旧版本内核或者 btrfs-progs 可能不能读取或者修复你的文件系统。
  • GRUBrEFInd 目前缺乏对 zstd 的支持,请使用没有启用 zstd 选项的独立 boot 分区或者使用其余已被支持的算法从新压缩引导文件,好比:
    $ btrfs filesystem defragment -v -clzo /boot/*

子卷

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

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

参阅下面的连接得到更多信息:

建立子卷

要建立一个子卷:

# btrfs subvolume create /path/to/subvolume

列出子卷列表

要列出当前路径 (path) 下的子卷:

# btrfs subvolume list -p path

删除子卷

要删除一个子卷:

# btrfs subvolume delete /path/to/subvolume

只是移除子卷的目录 /path/to/subvolume 而不使用这个命令并不会删除一个子卷.

挂载子卷

可使用 subvol=/path/to/subvolumesubvolid=objectid' 挂载标志来安装子卷,就像文件系统分区同样。例如,您能够拥有一个名为 subvol_root 的子卷,并将其挂载为 /。经过在文件系统的顶层建立各类子卷,而后将它们安装在适当的挂载点,能够模仿传统的文件系统分区。 所以,可使用#Snapshots[broken link: invalid section]轻松地将文件系统(或其一部分)恢复到先前的状态。

Tip: 为了方便地修改子卷的结构,请考虑建立新的子卷,而后挂载为 / 而不是使用顶层子卷 (ID=5) 挂载为根目录(这是默认行为)。

 

Note: “大多数挂载选项适用于 整个文件系统,而且只有要挂载的第一个子卷的选项才会生效。 这是由于没有实现,将来可能会发生变化。” [2] 查阅 Btrfs Wiki FAQ 以了解哪些挂载参数可以被用于独立的子卷

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

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

改变默认子卷

若是挂载时不指定 subvol= 选项便会挂载默认子卷.要改变默认子卷:

# btrfs subvolume set-default subvolume-id /

subvolume-id 能够经过#列出子卷列表得到.

Note: 在安装了 GRUB 的系统上,在改变默认子卷之后不要忘记运行 grub-install . 参见 this forum thread.

经过 btrfs subvolume set-default 修改默认子卷将会致使文件系统的最顶层没法访问,除非使用 subvol=/ 或者 subvolid=5 挂载参数。[3]

配额

Warning: 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 驱动器中释放未使用的块。

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

 

使用

显示已使用的/空闲空间

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

# btrfs filesystem usage /
Note: The btrfs filesystem usageRAID5/RAID6 设备上可能没法正常工做。

查看 [4] 以获取更多信息。

碎片整理

Btrfs 支持经过配置 挂载参数 autodefrag 来实如今线的碎片整理。要手动整理你的根目录的话,可使用:

# btrfs filesystem defragment -r /

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

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

RAID

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

Warning: 奇偶校验 RAID(RAID 5/6)代码中存在多个严重的数据丢失错误。 检查 Btrfs 的 Wiki RAID5/6 page 和 BUG 汇报 linux-btrfs mailing list 以获取更多信息。

Scrub

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

Warning: 运行 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 (使用一样的挂载点参数) ,相对于 # btrfs scrub 这么作的优势是会记录在 Systemd 日志中。

 

Balance

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

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

# btrfs balance start /
# btrfs balance status /

快照

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

要建立一个快照:

# btrfs subvolume snapshot source [dest/]name

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

加入 -r 参数能够建立一个只读快照. 为只读快照建立一个快照能够得到一个只读快照的可写入版本.

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

发送和接收

能够经过 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's Incremental Backup page 得到更多信息 (例如使用工具自动化这一过程)。

去重

使用写时复制,Btrfs可以复制文件或整个子卷而无需实际复制数据。可是,不管什么时候更改文件,都会建立一个新的 “真正的” 副本。重复数据删除更进一步,经过主动识别共享公共序列的数据块并将它们组合到具备相同写时复制语义的范围内。

专用于 Btrfs 分区去重的工具包括 duperemoveAUR,bedupAUR 和 btrfs-dedup。人们可能还但愿仅使用基于文件的级别对数据进行重复数据删除,好比 rmlint 或者 jdupesAUR。有关这些程序的可用功能的概述和其余信息,请查看上游 Wiki 条目

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

已知问题

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

加密

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

(若是已经建立了文件系统,可使用EncFSTrueCrypt,可是这样会没法使用 btrfs 的一些功能。)

交换文件

Btrfs 不支持交换文件,由于 Btrfs 有潜在的文件系统损坏风险,没有加入交换文件须要的功能,参阅这里。交换文件能够挂载到 loop 设备中,可是性能比较差。systemd-loop-swapfileAUR[broken link: archived in aur-mirror]提供了须要的服务文件。

TLP

使用 TLP 须要特殊的预防措施,以免文件系统损坏。有关更多信息,请参阅TLP#Btrfs

提示和技巧

无分区 Btrfs 磁盘

Warning: 大多数用户不但愿这种类型的设置,应该在常规分区上安装 Btrfs。 此外,GRUB 强烈建议不要安装到无分区磁盘。

Btrfs 能在整个设备上使用,替代 MBRGPT 分区表,可是并不要求必定这么作,最简单的方法是 在一个已存在的分区上建立 btrfs 文件系统[broken link: invalid section]. 若是你选择用 btrfs 替代分区表, 能够用 子卷[broken link: invalid section]模拟不一样的分区。下列是在单个无分区设备上使用 Btrfs 文件系统的限制:

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

# mkfs.btrfs /dev/sdX

若是设备上存在分区表,则须要使用:

# mkfs.btrfs -f /dev/sdX

例如 /dev/sda 而不是 /dev/sda1. 后一种形式会格式化现有的分区而不是替换掉原有的分区表.

像使用普通的 MBR 分区表存储设备同样安装 启动管理器, 参考 Syslinux#Manual installGRUB/Tips and tricks#Install to partition or partitionless disk

从 Ext3/4 转换

Warning: 到2015年中后期, btrfs 邮件列表中报告了多起失败的转换.尽管近期的更新有所修复,但仍是建议当心使用.在开始以前肯定你有 可用的备份而且愿意承担丢失数据的风险. 详见 Btrfs Wiki:从 Ext3 文件系统转换 .

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

# btrfs-convert /dev/partition

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

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

# btrfs subvolume delete /ext2_saved

最后经过 balance 回收空间.

请记住,以前安装的某些应用程序必须适配 Btrfs。值得注意的是 TLP#Btrfs 须要特别当心以免文件系统损坏,但其余应用程序也可能从某些功能中获益。

Checksum 硬件加速

要验证Btrfs校验和是不是硬件加速:

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

若是你看到 crc32c=crc32c-generic,这颇有多是由于你的根分区是 Btrfs,你将会须要编译 crc32c-intel 进入内核并启用它。将 crc32c-intel 放入 mkinitcpio.conf不会 生效的。

损坏恢复

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

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

Regenerate the initramfs

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

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

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

引导进入快照

为了可以引导进入快照,你必须经过 内核参数 rootflags=subvol=/path/to/subvolume 来指定子卷,同时须要修改 /etc/fstab 使用 subvol= 来指定相同的子卷。或者,子卷能够用其 id 来指定 - 例如能够用例如可检索的。 btrfs subvolume list /root/path - 和rootflags=subvolid=objectid 分别做为内核参数subvolid= objectid 做为 /etc/fstab 中的挂载选项。

若是使用 GRUB,则能够在 grub-btrfsgrub-btrfs-gitAUR 的帮助下从新生成配置文件时使用 Btrfs 快照自动填充启动菜单。

Use Btrfs subvolumes with systemd-nspawn

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

故障排除

参阅 Btrfs Problem FAQ 得到排除通常问题的信息.

GRUB

分区偏移

Note: 在试图将 core.img 嵌入到已经分区的磁盘上时可能会发生偏移问题. 这意味着能够把 corg.img 嵌入到 btrfs 池或是无分区磁盘 (例如 /dev/sdX) 上.

Grub 2能够启动 Btrfs 分区,可是由于模块比较大, grub-install 安装的 core.img 文件超过了 MBR 与第一个分区之间的空间大小 (63 扇区/31.5KiB) .更新后的 fdiskgdisk 的磁盘工具会经过第一个分区前空出 1-2M 的空间避免此问题.

Missing root

若是启动 RAID 卷设备后编辑了 /usr/share/grub/grub-mkconfig_lib 移除了 echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}" 中的引号,可能会遇到 error no such device: root 问题,从新生成 GRUB 设置文件应该能避免这个问题.

BTRFS: open_ctree failed

2014 年 11 月的 systemdmkinitcpio 中的 bug 可能致使使用 mkinitcpio.confbtrfs 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 内核参数

检查 btrfs 文件系统

Warning: btrfs (特别是 btrfs check 命令)仍在开发阶段, 强烈建议在加上 --repair 参数运行 btrfs check 时作一个 备份.

btrfs check 能够检查并修复一个未挂载的 btrfs 文件系统.可是因为它并未开发完成,它并不能修复某些错误 (即便这些错误没致使没法挂载).

参阅 Btrfsck 得到更多信息.

另见

更多参考

相关文章
相关标签/搜索