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 錯誤,就應停止寫入,把工作重點轉向資料搶救和硬體鏈路排查。