跳转到内容

Btrfs 维护:scrub、balance 与换盘 ​

读完这一篇,你能读懂 OMV 发给你的 scrub 报告和错误计数,在「明明有空间却写不进」时知道怎么查,并了解多盘 Btrfs 换盘的正确顺序和风险。创建 Btrfs 见 Btrfs:多盘、快照与数据校验。

这些操作大多只能在命令行做,界面帮不上忙

影响范围:整个 Btrfs 文件系统。balance 会重写大量数据,换盘期间文件系统的冗余会降低,用错参数可能让冗余配置降级。

前置条件:

  • 数据有独立备份。 快照和 RAID1 都不是备份,见备份策略。
  • 弄清文件系统用的是什么配置(btrfs filesystem usage 里的 Data 和 Metadata 行)。
  • 命令里的 <挂载点> 是 /srv/dev-disk-by-uuid-<UUID>,从 文件系统 页的挂载点列复制。

怎么回退:balance 可以中途取消,不会损坏文件系统。换盘和降级挂载没有回退,所以务必先备份。拿不准时先停手,带上命令输出向 Btrfs 社区(linux-btrfs 邮件列表)或 OMV 论坛求助。

下面所有命令都在 OMV 的 shell(SSH 或本机控制台,以 root 身份)里执行。

一、日常看状态 ​

OMV 界面的显示详情页给出 btrfs filesystem show、df、device stats 和 scrub status 四段输出。想自己看:

sh
btrfs filesystem usage <挂载点>
btrfs device stats <挂载点>
btrfs scrub status -d <挂载点>

三条都是只读的。别用 df 判断 Btrfs 还剩多少空间,官方文档说 btrfs filesystem df 原本是调试用的,输出需要进一步解读。usage 里最重要的两项:

  • Device unallocated:还没有被划成数据块或元数据块的空间。
  • Free (estimated):估计还能存多少数据。

二、scrub ​

作用与边界 ​

scrub 通读所有数据和元数据,核对校验和,能发现数据校验错误、超级块错误、元数据头错误和磁盘读错误。它不是 fsck,只通过校验和发现问题。

  • 有冗余副本时(RAID1、RAID10、元数据的 DUP),scrub 会用好的那份修复坏的那份。
  • 没有冗余副本时(数据用 Single),scrub 只能告诉你哪里坏了,修不了。
  • 对设置了 chattr +C(NOCOW)的文件,数据不校验,scrub 也检查不到。

OMV 怎么安排它 ​

默认每月一次,对每个已挂载的 Btrfs 运行 omv-btrfs-scrub。可调的环境变量(设置方法见环境变量):

变量默认作用
OMV_BTRFS_SCRUB_ENABLEDyes设成 no 关闭
OMV_BTRFS_SCRUB_PERIODmonthly设成 weekly 改成每周
OMV_BTRFS_SCRUB_ARGS空追加给 omv-btrfs-scrub 的参数
OMV_BTRFS_SCRUB_PRIORITY-c 2 -n 4传给 btrfs scrub start 的 I/O 优先级参数
OMV_BTRFS_SCRUB_READONLYno设成 yes 时加 -r,只读模式,不修复

官方文档对 scrub 的建议周期是每月,视情况可以更短。邮件报告需要开启系统通知,并在 系统 → 通知 → 事件(System → Notification → Events)里打开「杂项」,见配置邮件通知。

手动运行:

sh
omv-btrfs-scrub

它对所有已挂载的 Btrfs 依次 scrub 并输出报告。只想 scrub 一个文件系统:

sh
btrfs scrub start -B -d <挂载点>

-B 让它在前台运行,-d 按设备分别统计。scrub 会占去很大的 I/O,期间 NAS 变慢,官方文档估计空闲时约占设备带宽的 80%。

读结果 ​

sh
btrfs scrub status -d <挂载点>

重点看 Error summary 一行:

  • no errors found:没发现错误。
  • 其他:会列出各类错误的计数,以及已修复(corrected)和无法修复(uncorrectable)的数量。

遇到错误:

  1. 全部已修复:冗余副本救回来了。但盘上出现了坏数据,用 SMART 查这块盘,盘有问题就准备换。
  2. 有无法修复的:那些文件的内容已经坏了。内核日志里会记录受影响文件的路径,用 journalctl -k | grep -i btrfs 查。处理办法:从备份或快照里恢复这些文件,删掉坏的,再 scrub 一次确认。

错误计数 ​

Btrfs 给每块设备记五个累计计数:write_io_errs、read_io_errs、flush_io_errs、corruption_errs、generation_errs。corruption_errs 是校验和对不上,generation_errs 是块的代数不对。

OMV 每天用 btrfs device stats --check --reset 检查:有任一非零就写系统日志并发邮件,同时把计数清零。所以同一批错误只会提醒一次,收到邮件后别当没事,去看 btrfs device stats 和日志。你处理完之后想手动清零,用 btrfs device stats -z <挂载点>。

三、空间不足与 balance ​

为什么有空间却写不进 ​

Btrfs 分两级使用空间:先把设备上的空间划成数据块、元数据块,再往块里放文件。如果设备上已经没有未分配的空间(Device unallocated 接近 0),而元数据块写满了,即使数据块里还有大量空闲,也会报「没有剩余空间」。写时复制的特性还可能让删除文件也需要写元数据,所以别让 Btrfs 接近写满。

快照会让旧数据一直占着空间,删除快照后才会释放,见共享文件夹快照。

先清理,再考虑 balance ​

  1. 删不需要的快照和文件,先把空间腾出来。
  2. 仍不行,再用 balance,从最温和的过滤器开始:
sh
btrfs balance start -v -dusage=0 <挂载点>
btrfs balance start -v -dusage=10 <挂载点>

-dusage=N 表示只处理「使用率不超过 N%」的数据块。usage=0 清理完全空的块,不需要额外的工作空间;usage=10 把几乎空的块合并。官方文档的建议是从 5 或 10 这样的小值开始,处理得快,也能腾出空间;效果不够再逐步调大(20、30……)。

  1. balance 的进度和取消:
sh
btrfs balance status <挂载点>
btrfs balance cancel <挂载点>

官方文档说,balance 被取消或意外中断不会损坏文件系统;没完成的 balance 会在下次挂载时自动继续,除非挂载选项里有 skip_balance。

balance 不是日常维护 ​

官方文档把 balance 当作特定场景的工具:改配置(例如 Single 转 RAID1)、给条带类配置加盘后重新分布、腾出空间。没有这些情况时不用定期做,OMV 也没有安排 balance 的计划任务。不带过滤器的 balance 会把所有数据重写一遍,极耗时间和 I/O,机械盘上尤其明显。

做不下去时,别硬来,把 btrfs filesystem usage <挂载点> 的完整输出附上去求助。

四、扩容与加盘 ​

界面上的「扩充」。 文件系统 页的扩充按钮执行的是 btrfs filesystem resize max <挂载点>。官方文档说明,resize 不指定设备编号(devid)时,默认处理的是 devid 1。所以:

  • 单盘 Btrfs,底层磁盘变大后,直接点扩充。
  • 多盘 Btrfs,换了更大的盘之后,要对那块新盘单独扩:先用 btrfs filesystem show <挂载点> 看新盘的 devid,再用 btrfs filesystem resize <devid>:max <挂载点>。

加盘。 往已有的 Btrfs 里加盘要用 btrfs device add,加盘本身很快,不影响现有数据。想让新盘参与冗余,还要用 btrfs balance start -dconvert=… 转换配置并重新分布。OMV 界面做不到,官方文档的相关页面是 btrfs-device 和 Balance,先在测试环境演练。OMV 的旧版官方文档提到,用命令行给 Btrfs 加盘,OMV 不会因此出问题。

五、换盘 ​

用 btrfs replace,不要先 device remove 再 device add,也不要用 balance 把配置转成更低的冗余:Btrfs 文档明确说,换故障盘要用 replace。

盘还在线(SMART 预警、预防性更换) ​

  1. 先做一次备份,并对当前文件系统 scrub 一遍,确认现状。
  2. 接上新盘,在 存储器 → 磁盘(Storage → Disks)里做快速擦除,保证它没有旧的文件系统标记。
  3. 查要换的盘的 devid:
sh
btrfs filesystem show <挂载点>
  1. 开始替换,把 <devid> 换成要替换的盘的编号,<新盘> 换成新盘设备名(核对序号,不要写错):
sh
btrfs replace start <devid> /dev/<新盘> <挂载点>
btrfs replace status <挂载点>

replace start 会把旧盘上的数据复制到新盘,完成后旧盘自动从文件系统里去掉。文档说明新盘必须不小于旧盘,并且不能是已经挂载的设备。

  1. 新盘比旧盘大时,替换完成后要手动扩容:
sh
btrfs filesystem resize <devid>:max <挂载点>
  1. 再 scrub 一遍,给新盘开 SMART 监控。

盘已经掉线或损坏 ​

这种情况风险高得多,界面无能为力:

  • Btrfs 默认不允许以缺盘的状态挂载(degraded 选项默认关闭),所以重启后文件系统没有挂载上。
  • 要换盘,必须先用 degraded 方式挂载。官方文档提醒:以降级方式读写挂载时,新分配的块可能退回成 Single 之类的低冗余配置,事后要检查并 balance 回来。
  • 如果只是想先把数据取出来,用只读降级挂载最安全,它不会修改任何东西:
sh
mkdir -p /mnt/rescue
mount -o degraded,ro /dev/<剩余的盘> /mnt/rescue

把需要的数据复制出来,umount /mnt/rescue,再决定下一步。

读写降级挂载后做 btrfs replace、恢复冗余,这一整套待实机核实,也不属于一篇文章能保证安全的范围。建议先做完整备份,再按官方文档的步骤,必要时到用救援系统抢救数据和社区求助。

btrfs check --repair 是最后的手段

官方文档:「除非开发者或有经验的用户建议,否则不要用 --repair」,而且没有任何 fsck 能修复所有类型的损坏。btrfs check 默认只读,不会修改设备,想检查可以用它,但最好在卸载的文件系统上做。不要在挂载状态下用 --repair。

检查结果 ​

  • btrfs filesystem usage <挂载点> 里 Device unallocated 有足够的空间,Data 和 Metadata 的配置与你预期一致。
  • btrfs device stats <挂载点> 各项为 0。
  • 最近一次 btrfs scrub status 的 Error summary 是 no errors found。
  • 换盘后,btrfs filesystem show <挂载点> 里设备列表正确,新盘的 SMART 状态是「好」。

常见问题 ​

收到「Errors detected on Btrfs file system」邮件。 这是每日错误计数检查发的,见上面「错误计数」。计数已被清零,不会重复提醒。

scrub 总是被打断。 关机、挂起,或者你的内核较新时,系统休眠和信号也会中断 scrub。可以 btrfs scrub resume 继续,官方文档说它会从上次保存的位置接着做。

balance 报「没有剩余空间」。 工作空间不够。先用 usage=0 清理完全空的块;仍不行,停下来,保留输出求助。

想把 Single 的 Btrfs 转成 RAID1。 加盘之后用 balance 转换配置,见上面的加盘一节,先备份并演练。

参考资料 ​

OpenMediaVault 非官方中文使用指南,与 openmediavault 项目及其开发者无隶属关系。