我终于也是 Btrfs 人了!

Arch 群人均 Btrfs 用户,我对 Btrfs 也垂涎已久,这次趁着换硬盘把文件系统也一并换了,记录一下折腾过程,供后人参考。

迁移系统

btrfs-convert

这是一个能够将 ext4 文件系统原地转换至 Btrfs 的工具1,它应该是比较稳定的,至少回滚功能做得不错。如果你没有额外硬盘备份你的数据,但又十分想用 Btrfs,则可以考虑使用它来进行原地转换。

不过我第一次使用它时就遇到了 bug,导致转换完的文件系统无法挂载,虽然最后成功回滚了,但是也不敢再用这个工具进行转换了……(当然这个 bug 目前已经修复了2

备份

仙子有两篇关于这个的文章3,照抄里面的 rsync 命令就行了。

为了进一步节省备份的时间与空间,建议先使用 filelight、ncdu、dua-cli 等工具检查一下磁盘,把 target、node_modules 等「占用空间大」或者「文件数量多」的缓存文件夹都删掉。

格式化

mkfs.btrfs 会根据情况自动选择合适的参数,一般只需要补一个 -L 指定一下 label 即可。

但是,如果你用 RAID、或者是在虚拟机里装的 Linux,那可能需要调整一下 -d-m 参数4

分区

如果作为系统盘建议分一个 512M 的 FAT32 EFI 分区,否则不用分,Btrfs 有棒棒的子卷可以代替。

如果你的 Linux 内核版本小于 5.0 并且你需要使用 SWAP 的话,则建议再分一个交换分区5

子卷布局

格式化完后,先别急着把数据移回来。为了更好地使用 Btrfs 的快照功能,我们需要建立一些子卷。

关于子卷的布局不同人有不同的想法,我参考了一堆资料6,最终决定采用平坦子卷布局。建立了 @、@home、@swap、@var 四个顶层子卷,再为 ~/.cache 单独创建一个子卷。

创建这么多子卷的好处有啥呢……主要是为了方便快照。Btrfs 的快照是以子卷为单位的,而 /swap /var .cache 这种东西修改地非常频繁,如果将它们包含在快照中的话,快照的体积会增大的非常快。这好吗?这不好。所以得把它们放到单独的子卷中。

创建完子卷就可以把东西扔回去了,不过如果想要透明压缩的时候记得在挂载的时候就指定 compress

挂载参数

Btrfs 有很多挂载参数,考古了一下 Arch 群的历史发言记录,我决定采用 noatime,space_cache=v2,compress=zstd,然后为 SSD 加上 discard=async,HDD 加上 autodefrag

  • noatime:对于拥有 CoW 的 Btrfs 来讲,即使是修改时间戳这种简单的写入也会带来不小的开销,因此 noatime 某些情况下可以显著提高性能
  • space_cache=v2:fc 教授建议加上的,对大磁盘有优化,据说以后将会成为 Btrfs 的默认设置
  • compress=zstd:使用 zstd 压缩,有些人会推荐使用 compress-force,但根据 Btrfs manual 的说法,4.15 以后应该没有使用 compress-force 的必要了。
  • discard=async:异步 trim
  • autodefrag:相比手动运行 defrag,autodefrag 更不容易断开 reflink。

维护

碎片检测

CoW 的文件系统都很容易产生碎片,建议在正常使用一段时间后参照仙子的文章检测一下。为其中碎片过多的文件关闭 CoW。

需要注意的是,如果你开启了压缩,那么碎片会比通常情况下多不少。因为考虑到主流压缩算法都不支持随机访问,要想访问某段数据就得解压整个块,所以压缩文件的最大 extent 大小被限制为 128KiB,而通常的最大 extent 大小是 128MiB。

也就是说,如果有个 1GiB 的可压缩文件,那它大概会碎成 8192 块,这是正常的,不需要管,如果远超这个数字,才需要考虑是不是得关闭 CoW(这同样会禁用压缩)。

SQLite

SQLite 的 Write-Ahead Logging 可以有效提升 CoW 文件系统下的性能,如果检测到某个 SQLite 数据库的碎片过多,可以使用这种方案来手动优化一下。

注:主流软件比如 Chromium、Firefox 都已经采用 WAL 了

Docker

Docker 默认使用的是支持 CoW 的 OverlayFS2,但是底层文件系统已经支持 CoW 了就没有再套一层 CoW 的必要了,这是完全的负优化。

因此建议参考 https://docs.docker.com/storage/storagedriver/btrfs-driver/ 将 storage driver 替换为 btrfs

快照

为什么馋 Btrfs?一个是压缩,另一个就是快照了。

利用了 CoW 特性的 Btrfs 快照非常轻量,不少 Btrfs 用户都是每小时给系统照一次快照,非常奢侈。

去重


  1. https://btrfs.wiki.kernel.org/index.php/Conversion_from_Ext3 ↩︎

  2. Btrfs_(简体中文)#从_Ext3/4_转换 ↩︎

  3. rsync+btrfs+dm-crypt 备份整个系统迁移系统到 SSD ↩︎

  4. mkfs.btrfs(8) ↩︎

  5. btrfs.5#SWAPFILE_SUPPORT ↩︎

  6. Arch WikiOpenSUSE WikiBtrfs Wiki,以及 fc 教授的博客 ↩︎