外观
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_ENABLED | yes | 设成 no 关闭 |
OMV_BTRFS_SCRUB_PERIOD | monthly | 设成 weekly 改成每周 |
OMV_BTRFS_SCRUB_ARGS | 空 | 追加给 omv-btrfs-scrub 的参数 |
OMV_BTRFS_SCRUB_PRIORITY | -c 2 -n 4 | 传给 btrfs scrub start 的 I/O 优先级参数 |
OMV_BTRFS_SCRUB_READONLY | no | 设成 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)的数量。
遇到错误:
- 全部已修复:冗余副本救回来了。但盘上出现了坏数据,用 SMART 查这块盘,盘有问题就准备换。
- 有无法修复的:那些文件的内容已经坏了。内核日志里会记录受影响文件的路径,用
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
- 删不需要的快照和文件,先把空间腾出来。
- 仍不行,再用 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……)。
- 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 预警、预防性更换)
- 先做一次备份,并对当前文件系统 scrub 一遍,确认现状。
- 接上新盘,在
存储器 → 磁盘(Storage → Disks)里做快速擦除,保证它没有旧的文件系统标记。 - 查要换的盘的 devid:
sh
btrfs filesystem show <挂载点>- 开始替换,把
<devid>换成要替换的盘的编号,<新盘>换成新盘设备名(核对序号,不要写错):
sh
btrfs replace start <devid> /dev/<新盘> <挂载点>
btrfs replace status <挂载点>replace start 会把旧盘上的数据复制到新盘,完成后旧盘自动从文件系统里去掉。文档说明新盘必须不小于旧盘,并且不能是已经挂载的设备。
- 新盘比旧盘大时,替换完成后要手动扩容:
sh
btrfs filesystem resize <devid>:max <挂载点>- 再 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 转换配置,见上面的加盘一节,先备份并演练。
参考资料
- Btrfs 文档:Scrub、Balance、btrfs-replace、btrfs-device、btrfs-filesystem、btrfs-check 与 btrfs(5)
- OMV 源码:
omv-btrfs-scrub、etc/cron.monthly、etc/cron.weekly与etc/cron.daily里的 Btrfs 脚本、FileSystemMgmt与Btrfs文件系统类