HC620 叠瓦盘写满后 Btrfs 变只读怎么办:安全腾空间与排障指南

讲解 HC620 Host-Managed SMR 硬盘上的 Btrfs zoned 写满后变只读时,如何保存日志、判断 ENOSPC 与 I/O 错误、安全腾出空间、谨慎 balance,并验证文件系统恢复。

HC620 使用 Btrfs zoned 时,如果文件系统接近 100%,随后突然只能读取、不能写入,最常见的线索确实是 ENOSPC、zone reclaim 没有足够工作空间,或者事务提交失败后被内核强制切换为只读。

但“写满”和“只读”只能说明故障发生时的表象,不能直接证明硬盘没有损坏。正确顺序是:

  1. 立即停止写入任务;
  2. 保存故障发生时的内核日志;
  3. 确认设备、挂载状态与 zoned 空间分布;
  4. 区分纯空间耗尽、回收受阻、事务中止和底层 I/O 错误;
  5. 只有证据支持纯 ENOSPC 时,才尝试重新以读写方式挂载并分批腾空间;
  6. 空间恢复后再做低风险整理和完整验收。

不要一看到只读就执行 mount -o remount,rw、全盘 balance 或 btrfs check --repair。强制只读是文件系统的保护结果,先找出触发它的第一条错误。

本文假设挂载点是 /mnt/hc620。设备名仅用 /dev/sdX 表示,执行前必须替换成实际设备或分区。不要照抄盘符。

为什么 HC620 写满后比普通硬盘更难腾空间

Western Digital Ultrastar DC HC620 是 Host-Managed SMR,也就是由主机管理写入区域的叠瓦盘。

Linux 通常把它暴露为 zoned block device:

1
lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,ZONED,MOUNTPOINTS

预期能看到类似:

1
2
NAME MODEL              SIZE TYPE FSTYPE ZONED        MOUNTPOINTS
sda  HSH721414ALE6M0   12.7T disk btrfs  host-managed /mnt/hc620

实际型号、容量显示和设备名可能不同,以本机输出为准。

普通 CMR 硬盘可以在已分配扇区上覆盖写入。Host-Managed SMR 的顺序写 zone 则必须从当前写指针继续写;要重新使用一个写过的 zone,通常需要先搬走仍然有效的数据,再 reset 整个 zone。

Btrfs 从 Linux 5.12 起支持 zoned mode。它采用 COW,文件覆盖、元数据更新或删除后,旧数据块可能不再被文件系统引用,却不会立刻变成可重新写入的空 zone。

这些空间会在 btrfs filesystem usage 中显示为:

1
Device zone unusable

它的含义不是“永久坏掉的硬盘容量”,而是过去写过、现在已经没有引用,但仍需经过 block group reclaim 和 zone reset 才能重新使用的空间。

回收过程需要把 zone 中仍有效的数据搬到新位置。如果已经没有足够的新 zone 可接收这些数据,就可能出现暂时性 ENOSPC

因此,在 HC620 上:

1
文件层面删除了 1 TiB

不一定立即等于:

1
底层马上多出 1 TiB 可写空间

这也是 zoned Btrfs 真正写到极限后,比普通盘更难现场处理的原因。

第一时间停止哪些任务

发现挂载点只读后,不要反复重试原来的复制任务。

先停止可能继续制造 I/O 或日志噪声的服务,例如:

  • rsyncrclone 或下载任务;
  • 容器和虚拟机;
  • 媒体库扫描;
  • 定时快照和备份;
  • scrub、balance 或大规模删除任务。

先确认当前是否有 balance 或 scrub:

1
2
sudo btrfs balance status /mnt/hc620
sudo btrfs scrub status /mnt/hc620

不要为了执行本文命令而机械取消任务。先记录状态;如果 balance 或 scrub 正在运行并且系统仍有响应,应结合日志判断它是否就是故障现场的一部分。

查看有哪些进程仍占用挂载点:

1
sudo fuser -vm /mnt/hc620

这条命令只做观察,不会自动终止进程。

先保存故障日志,再卸载或重启

dmesg 中最有价值的往往不是最后一行 forced readonly,而是它之前最早出现的错误。

先保存完整内核日志到另一块正常磁盘,例如系统盘:

1
sudo journalctl -k -b --no-pager > "$HOME/hc620-kernel-current-boot.log"

再提取相关行:

1
2
3
sudo dmesg -T | \
grep -iE 'btrfs|enospc|no space|transaction|abort|forced readonly|zone|I/O error' | \
tail -200

如果机器已经重启过,查看上一次启动:

1
2
sudo journalctl -k -b -1 --no-pager | \
grep -iE 'btrfs|enospc|no space|transaction|abort|forced readonly|zone|I/O error'

如果系统没有持久化 journal,上一次启动的日志可能不存在。因此故障现场应尽量先导出日志,再重启。

同时保存基本环境:

1
2
3
4
uname -a
btrfs version
lsblk -o NAME,MODEL,SERIAL,SIZE,TYPE,FSTYPE,ZONED,MOUNTPOINTS
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /mnt/hc620

其中 findmntOPTIONS 如果包含 ro,只能确认当前挂载是只读,不能说明为什么变成只读。

确认设备身份,禁止凭感觉填写 /dev/sdX

先从挂载点反查源设备:

1
findmnt -no SOURCE /mnt/hc620

再查看文件系统中的设备:

1
sudo btrfs filesystem show /mnt/hc620

确认稳定设备链接:

1
ls -l /dev/disk/by-id/

如果文件系统建在分区上,后续挂载必须使用该分区,而不是整盘。比如实际源设备是 /dev/sda1,就不能写成 /dev/sda

把实际结果记录为变量时,也要人工核对:

1
2
3
4
5
DEV=/dev/disk/by-id/你的实际设备或分区链接
MNT=/mnt/hc620

lsblk -f "$DEV"
findmnt "$MNT"

不要把示例中的中文占位符原样执行。

读取 Btrfs 空间分布

文件系统仍处于挂载状态时执行:

1
2
3
sudo btrfs filesystem usage -T /mnt/hc620
sudo btrfs filesystem df /mnt/hc620
sudo btrfs device usage /mnt/hc620

重点记录:

1
2
3
4
5
6
7
Device size
Device allocated
Device unallocated
Device zone unusable
Data,single
Metadata,single 或 Metadata,DUP
Global reserve

典型的高风险组合类似:

1
2
3
4
5
Device allocated:       接近 Device size
Device unallocated:     0.00 B 或非常少
Device zone unusable:   数十至数百 GiB
Data 使用率:            接近 100%
Metadata 使用率:        很高

不要只看 df -h。Btrfs 的数据、元数据、system block group 和设备未分配空间是不同层次;COW 还需要新的空间完成事务。

Device zone unusable 也不能单独作为故障结论:

  • 数值非零是 zoned COW 工作后的正常现象;
  • 数值很大且 Device unallocated 接近 0,才说明可回收空间与立即可分配空间严重错位;
  • 数值在后台回收期间可能变化;
  • 即使它为 0,也不能排除元数据耗尽或底层 I/O 错误。

检查持久化设备错误计数

执行:

1
sudo btrfs device stats /mnt/hc620

正常输出示例:

1
2
3
4
5
[/dev/sda].write_io_errs    0
[/dev/sda].read_io_errs     0
[/dev/sda].flush_io_errs    0
[/dev/sda].corruption_errs  0
[/dev/sda].generation_errs  0

各项含义:

  • write_io_errs:下层块设备未能完成写请求;
  • read_io_errs:下层块设备未能完成读请求;
  • flush_io_errs:带 FLUSH 的写入失败,关系到事务落盘顺序;
  • corruption_errs:发现校验不匹配或损坏的元数据头;
  • generation_errs:块的 generation 与父节点期望不一致。

全为 0 是好迹象,但不是“硬盘一定健康”的证明。还要结合内核日志、SMART、HBA 和链路错误判断。

暂时不要使用:

1
sudo btrfs device stats -z /mnt/hc620

-z 会在打印后清零计数。故障证据尚未保存时清零,会丢失重要基线。

如果确实要观察错误是否继续增加,先保存当前输出,再记录时间:

1
2
date -Is
sudo btrfs device stats /mnt/hc620

完成受控测试后再次比较,而不是只看某一次快照。

用日志把故障分成四类

第一类:纯空间耗尽或临时 ENOSPC

更支持这一类的证据包括:

1
2
3
4
No space left on device
ENOSPC
transaction aborted
forced readonly

同时满足:

  • btrfs device stats 没有非零错误;
  • 日志中没有 I/O error
  • 没有 checksum、tree-checker、corrupt leaf 或 parent transid 错误;
  • 文件系统确实接近写满;
  • Device unallocated 很少,或 zoned 回收明显受限。

这种情况才适合进入后面的“受控读写挂载并腾空间”流程。

第二类:zone reclaim 或 block group 回收受阻

日志可能出现:

1
2
3
4
5
btrfs-cleaner
btrfs_delete_unused_bgs
btrfs_zone_finish
do_zone_finish
blocked for more than ... seconds

此时问题不一定只是容量数字归零,还可能涉及特定内核下的回收路径、长时间锁等待或 zoned 活跃 zone 限制。

不要在这时追加全盘 balance。先保留调用栈、内核版本和完整日志,再参考站内的真实故障复盘:

HC620 上 Btrfs zoned 两次故障复盘:锁死、只读与内核排查

第三类:事务中止,但原因尚未确定

下面几行只说明结果:

1
2
3
transaction aborted
BTRFS error
forced readonly

真正原因通常在前面。要向上查几十到几百行,找到第一条错误、返回码和调用栈。

不能把所有 transaction aborted 都归类成写满。底层写失败、元数据验证失败和内核缺陷同样可能中止事务。

第四类:I/O、校验或结构错误

出现以下任一线索,应停止“删点文件就能修好”的流程:

1
2
3
4
5
6
7
8
9
I/O error
write_io_errs
read_io_errs
flush_io_errs
checksum error
corrupt leaf
parent transid verify failed
tree-checker
zone write pointer

这时优先保护数据副本,检查磁盘、SAS/SATA HBA、线材、供电和内核 zoned 错误。不要把设备计数非零简单解释为“只是满盘”。

先做只读挂载与数据抢救

如果当前挂载还能读,先复制最重要且没有其他副本的数据。

若需要卸载后重新挂载,先退出占用目录的 shell,再执行:

1
2
cd /
sudo umount /mnt/hc620

确认已经卸载:

1
findmnt /mnt/hc620

没有输出才表示该挂载点不在当前挂载表中。

先以只读方式挂载:

1
2
sudo mount -o ro "$DEV" /mnt/hc620
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /mnt/hc620

然后复制重要文件到另一块健康磁盘。只读抢救时不要把目标目录放回 HC620 本身。

如果普通只读挂载失败,不要随机叠加 rescue= 参数。不同错误需要不同救援选项,错误参数可能掩盖日志或改变读取结果,应根据具体报错再决定。

什么时候才允许尝试重新读写挂载

同时满足以下条件时,可以考虑一次受控尝试:

  • 已保存故障日志;
  • 重要数据有其他副本,或已先完成只读抢救;
  • 日志的第一原因明确指向 ENOSPC
  • 没有 I/O、校验、tree-checker 或 zone write pointer 错误;
  • btrfs device stats 没有异常计数;
  • 没有卡住的旧内核任务;
  • 文件系统可以干净卸载。

先卸载只读挂载:

1
sudo umount /mnt/hc620

再做一次普通挂载,不使用 remount,rw 强顶当前错误状态:

1
sudo mount "$DEV" /mnt/hc620

立即验证:

1
2
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /mnt/hc620
sudo dmesg -T | tail -100

如果挂载选项仍然包含 ro,或者日志再次出现事务中止,停止尝试,不要循环卸载、挂载。

如果成功显示 rw,也不要马上恢复复制服务。读写窗口的第一个任务是分批释放已知可删除的数据。

读写恢复后怎样安全腾空间

优先选择已经确认有其他副本、可以重建、并且体积大的目录。

先查看一级目录大小:

1
sudo du -xhd1 /mnt/hc620 | sort -h

不要直接照抄:

1
rm -rf /mnt/hc620/某个大目录

应先打印真实目标,确认没有变量展开错误:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
DELETE_TARGET=/mnt/hc620/已确认可删除的实际目录
DELETE_TARGET=$(realpath -e -- "$DELETE_TARGET") || exit 1

case "$DELETE_TARGET" in
  /mnt/hc620/*) ;;
  *) printf '拒绝删除挂载点之外的路径:%s\n' "$DELETE_TARGET" >&2; exit 1 ;;
esac

printf '%s\n' "$DELETE_TARGET"
sudo du -sh -- "$DELETE_TARGET"
sudo find "$DELETE_TARGET" -xdev -maxdepth 1 -mindepth 1 -printf '%f\n' | head

确认目标正确后再删除:

1
2
sudo rm -rf -- "$DELETE_TARGET"
sync

对于多 TB 数据,建议按独立子目录或批次删除,不要同时进行大规模写入。

每批后检查:

1
2
3
4
sudo btrfs filesystem sync /mnt/hc620
sudo btrfs filesystem usage -T /mnt/hc620
sudo btrfs device stats /mnt/hc620
sudo dmesg -T | tail -100

btrfs filesystem sync 可能需要一段时间。命令返回前不要把“目录消失”误当成空间已经完成回收。

应先以释放数百 GiB 的量级为目标,而不是只删几 GiB 后马上继续灌满。具体安全余量取决于工作负载、zone 大小、元数据和回收效率,不能给所有 HC620 一个绝对比例。

长期使用中,不建议把 zoned Btrfs 维持在 99%~100%。要同时预留:

  • 日常新写入空间;
  • COW 事务空间;
  • 元数据增长空间;
  • zone reclaim 搬运仍有效数据的工作空间;
  • 应急删除和维护窗口。

删除后为什么空间可能没有立即回来

删除文件主要解除引用并更新元数据。对于 zoned 设备,相关 zone 里可能还有有效 extent,Btrfs 必须先迁走它们,才能 reset zone。

因此可能看到:

  • 文件已经删除;
  • Used 有所下降;
  • Device zone unusable 暂时上升;
  • Device unallocated 没有按删除量同步增加;
  • 后台 cleaner 继续产生 I/O。

这不一定表示删除失败。观察一段完整的受控回收周期,并以日志和 btrfs filesystem usage -T 的趋势判断。

如果数值长期不变化,同时出现 cleaner 阻塞、事务错误或 D 状态任务,就应按回收路径故障处理,而不是继续大量删除。

balance 只能在空间恢复后逐步执行

balance 会搬移 block group。大多数 balance 操作需要先创建新的 block group 作为工作空间,因此满盘时直接运行无过滤器的 balance 可能再次触发 ENOSPC

不要一上来执行:

1
sudo btrfs balance start /mnt/hc620

先确认当前没有 balance:

1
sudo btrfs balance status /mnt/hc620

在日志稳定、已经释放空间、设备错误计数没有增长的前提下,可以先处理完全未使用的 block group:

1
sudo btrfs balance start -dusage=0 -musage=0 /mnt/hc620

usage=0 不需要额外工作空间,是 Btrfs 官方文档针对 ENOSPC 给出的低风险起点。

完成后检查:

1
2
3
4
sudo btrfs balance status /mnt/hc620
sudo btrfs filesystem usage -T /mnt/hc620
sudo btrfs device stats /mnt/hc620
sudo dmesg -T | tail -100

只有空间和日志都稳定时,才考虑低阈值:

1
sudo btrfs balance start -dusage=5 /mnt/hc620

再次观察后,才可能提高到:

1
sudo btrfs balance start -dusage=20 /mnt/hc620

这些数字不是必须逐级执行的固定处方。阈值越高,可能搬移的数据越多,所需工作空间和 I/O 也越大。

如果之前已经出现 btrfs-cleaner、block group 删除或 zone finish 路径卡死,不要把 balance 当成自动修复。它可能重新进入相近代码路径,应先查清内核问题。

不要在故障盘上做的操作

不要强制 remount 为读写

避免:

1
sudo mount -o remount,rw /mnt/hc620

如果内核刚刚因为错误把文件系统强制只读,直接 remount 会跳过“保存日志、卸载、重新评估”的边界,而且通常不能消除导致只读的根因。

不要盲目执行全盘 balance

避免:

1
sudo btrfs balance start /mnt/hc620

满盘 balance 需要搬移数据,可能比原故障需要更多临时空间。

不要运行 btrfs check --repair

避免:

1
sudo btrfs check --repair /dev/sdX

Btrfs 官方文档明确警告:除非得到开发者或有经验人员针对具体错误的建议,否则不要使用 --repair

如果确实需要离线结构检查,必须先卸载,并默认使用只读模式:

1
sudo btrfs check --readonly "$DEV"

但对 14TB 或 15TB 文件系统,这项检查可能耗时很长、占用大量内存并产生持续读取。只有纯 ENOSPC 证据时,通常不需要把它当作第一步。

不要先清零设备错误统计

避免在保存证据前执行:

1
sudo btrfs device stats -z /mnt/hc620

清零不会修复硬盘、线材或 HBA,只会抹掉比较基线。

不要继续边删边写

Host-Managed SMR 上数 TB 删除、zone reclaim 和数 TB 新写入重叠,会显著扩大故障面。

更稳妥的流程是:

1
2
3
4
5
6
停止新写入
→ 分批删除
→ 等待事务提交与回收
→ 检查空间和日志
→ 保留明显余量
→ 再分批恢复写入

空间恢复后的验收

恢复 rw 只是开始,不能作为最终成功标准。

验证挂载状态

1
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /mnt/hc620

确认:

  • 源设备正确;
  • 文件系统为 btrfs
  • 挂载选项包含 rw
  • 没有挂错子卷或分区。

验证空间分布

1
2
sudo btrfs filesystem usage -T /mnt/hc620
sudo btrfs device usage /mnt/hc620

不要只追求 Device zone unusable 归零。更重要的是:

  • 已经有足够可用空间;
  • Device unallocated 或可分配空间恢复;
  • 元数据不再逼近极限;
  • 回收过程中没有新错误。

验证错误计数没有增长

1
2
date -Is
sudo btrfs device stats /mnt/hc620

与故障后保存的基线比较。如果 write_io_errsflush_io_errscorruption_errsgeneration_errs 增长,停止恢复大规模写入。

验证内核没有再次强制只读

1
2
sudo journalctl -k --since '-30 min' --no-pager | \
grep -iE 'btrfs|enospc|no space|transaction|abort|forced readonly|zone|I/O error'

关注新产生的日志,不要把几小时前的旧错误误判为刚刚复发。

做小规模写入测试

先写到一个明确的测试目录:

1
2
3
4
5
TEST_DIR=/mnt/hc620/.recovery-test
sudo mkdir -p "$TEST_DIR"
sudo dd if=/dev/zero of="$TEST_DIR/test.bin" bs=1M count=1024 status=progress
sync
sudo sha256sum "$TEST_DIR/test.bin"

删除测试文件并再次提交:

1
2
3
sudo rm -f "$TEST_DIR/test.bin"
sudo rmdir "$TEST_DIR"
sudo btrfs filesystem sync /mnt/hc620

随后再次检查日志、空间和设备统计。

1GiB 测试通过只能证明小规模写入成功,不能证明数 TB 持续写入一定稳定。正式任务应从小批量恢复,并保留监控。

有冗余或备份后再安排 scrub

scrub 会读取全部已分配数据并验证校验和,可能持续很久。不要在刚恢复的满盘上立刻与 balance、复制和删除同时运行。

确认文件系统稳定且重要数据有副本后,再安排独立维护窗口:

1
sudo btrfs scrub start -Bd /mnt/hc620

完成后查看:

1
2
sudo btrfs scrub status /mnt/hc620
sudo btrfs device stats /mnt/hc620

单盘 single 数据没有另一份镜像可供 Btrfs 自动修复。scrub 能发现校验问题,不等于一定能修复。

长期避免再次写满的做法

给写入任务设置容量停止线

不要让备份脚本只看命令退出码。写入前后都记录:

1
2
df -h /mnt/hc620
sudo btrfs filesystem usage -T /mnt/hc620

当可用空间低于你的维护阈值时,停止接收新数据并告警。

阈值不应只按“还能放下下一个文件”计算,还要包含 COW、元数据和 zone reclaim 的空间。

把大量删除和大量写入错开

推荐:

1
2
3
4
5
复制一批
→ 校验一批
→ 等待事务稳定
→ 删除一批旧数据
→ 再检查 zone 与日志

不要安排 rsync、快照删除、scrub 和 balance 在同一个维护窗口中争抢 I/O。

对归档数据保留外部清单

可为重要目录生成校验清单,并把清单复制到另一块磁盘:

1
2
cd /mnt/hc620/archive
find . -type f -print0 | sort -z | xargs -0 sha256sum > /另一块盘/archive.sha256

文件名中包含换行符时,上面的文本清单格式仍可能不便处理;如果数据来源会产生特殊文件名,应使用支持 NUL 分隔的专用清单流程。

不把单盘文件系统当成备份

Btrfs 校验和能发现静默损坏,但单盘数据 profile 通常没有第二份数据副本可恢复。

HC620 上的数据至少还应有:

  • 另一块本地磁盘副本;
  • 另一台机器或异地副本;
  • 可定期验证的对象存储或离线副本。

常见问题

Device zone unusable 很大,是否说明盘坏了

不一定。它表示过去写过、现在因 COW 不再被引用、但尚未经过回收和 zone reset 的空间。

应同时看 Device unallocated、数据与元数据使用率、内核日志、回收趋势和设备错误计数。

删除文件后能马上恢复同等容量吗

不能保证。删除先改变文件系统引用,底层 zone 还可能需要搬移有效数据并 reset。

正常重新挂载成功,是否就能继续写满

不能。应先腾出明显余量,确认日志和错误计数稳定,再做小规模测试,最后分批恢复业务。

write_io_errs 为 0,是否排除硬盘问题

不能完全排除。它只说明 Btrfs 记录的该类持久化计数没有写失败;还要检查内核块层日志、SMART、HBA、线材和供电。

可以使用 mount -o recovery

不要把旧教程里的 recovery 当成通用修复开关。当前 Btrfs 的救援挂载选项有明确适用错误,而且通常要求只读挂载,应根据实际日志选择。

为什么 df 显示还有空间却报 ENOSPC

Btrfs 的 COW、数据与元数据 block group、事务预留和 zoned 回收都需要空间。df 展示的文件级可用估算不能完整表达这些内部约束。

要不要把元数据从 DUP 改成 single

不要仅为了挤出空间就临时改变 profile。profile 转换本身要搬移 block group,需要工作空间和大量 I/O;zoned 模式支持的 profile 还受内核与工具版本约束。

usage=0 balance 为什么相对安全

因为它只扫描并回收完全未使用的 block group,官方文档说明该过滤器不需要额外工作空间。

“相对安全”仍不等于适合所有故障。如果日志显示回收路径卡死或结构错误,先停止并分析。

能否直接断电重启

如果系统仍有响应,应先保存日志、停止任务、等待必要事务并正常卸载。强制断电会增加未提交写入和故障分析的不确定性。

如果内核任务长时间处于不可中断 D 状态、机器无法正常关机,应先通过另一台机器或远程控制台保存尽可能多的日志,再评估重启风险。

一份可执行的故障清单

按顺序执行,不要跳到 balance 或 repair:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
1. 停止复制、下载、容器、快照和维护任务
2. 保存当前及上一次启动的内核日志
3. 用 findmnt 和 lsblk 确认设备、分区、zoned 与 ro/rw
4. 保存 btrfs filesystem usage -T
5. 保存 btrfs device stats,不清零
6. 找到 forced readonly 前的第一条错误
7. 区分 ENOSPC、回收阻塞、事务异常和 I/O/结构错误
8. 有重要数据时先只读挂载并复制到另一块盘
9. 仅在纯 ENOSPC 证据充分时尝试一次普通读写挂载
10. 读写成功后分批删除已确认可重建的数据
11. 每批后 sync,并检查空间、日志和错误计数
12. 空间充裕且日志稳定后,才考虑 usage=0 balance
13. 做小规模写入、删除与校验测试
14. 独立维护窗口再安排 scrub
15. 给未来写入设置容量停止线和外部告警

需要收集哪些输出才能继续判断

如果仍无法确认属于哪一类,收集以下输出时隐藏序列号等敏感信息,但不要删掉错误上下文:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
uname -a
btrfs version

lsblk -o NAME,MODEL,SIZE,TYPE,ZONED,FSTYPE,MOUNTPOINTS
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /mnt/hc620

sudo btrfs filesystem usage -T /mnt/hc620
sudo btrfs device stats /mnt/hc620

sudo journalctl -k -b --no-pager | \
grep -iE 'btrfs|zone|enospc|no space|I/O error|transaction|abort|forced readonly' | \
tail -200

根据这些输出,通常可以把下一步收敛到:

  1. 单纯写满,可以受控腾空间;
  2. zone reclaim 没有工作空间或回收路径阻塞;
  3. Btrfs 事务中止,需要追溯首条错误;
  4. HC620、HBA、线材或供电出现真实 I/O 故障;
  5. 文件系统出现校验或结构错误,需要先抢救数据再由有经验人员处理。

参考资料

HC620 写满后变只读,最重要的不是尽快让它重新显示 rw,而是先判断内核为什么保护性只读。只有证据明确支持纯 ENOSPC,才应在保存日志和数据副本后受控腾空间;一旦出现 I/O、校验、结构或 zone write pointer 错误,就应停止写入,把工作重点转向数据抢救和硬件链路排查。