Btrfs 文件系统运维完全教程 / 第 14 章:故障排查
第 14 章:故障排查
14.1 常见故障分类
| 故障类型 | 严重程度 | 发生频率 |
|---|---|---|
| 空间不足 (enospc) | 中 | 常见 |
| 只读文件系统 | 高 | 偶发 |
| 设备故障 | 高 | 偶发 |
| 数据损坏 | 严重 | 罕见 |
| 内核 panic | 严重 | 罕见 |
| 挂载失败 | 高 | 偶发 |
14.2 空间不足问题 (enospc)
14.2.1 问题描述
# 症状:系统报告 "No space left on device"
$ touch /data/testfile
touch: cannot touch '/data/testfile': No space left on device
# 但 df 显示有空间!
$ df -h /data
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 100G 10G 90G 10% /data
14.2.2 原因分析
Btrfs 的 enospc 问题可能由以下原因导致:
| 原因 | 说明 |
|---|---|
| 块组碎片化 | 有空间但无法分配连续的块组 |
| 配额限制 | 子卷配额已满 |
| 元数据空间不足 | 元数据块组已满 |
| 快照占用 | 快照保留了旧数据块 |
| balance 挂起 | 之前的 balance 未完成 |
14.2.3 诊断步骤
# 1. 查看详细空间使用
sudo btrfs filesystem usage /data
# 重点关注:
# Device unallocated: 0.00B ← 如果为 0,说明块组全部已分配
# Data ratio: 1.00
# Metadata ratio: 2.00
# 2. 查看块组分配
sudo btrfs filesystem df /data
# Data,single: total=98.00GiB, used=10.00GiB ← 数据块组分配了很多
# Metadata,DUP: total=2.01GiB, used=200.00MiB ← 元数据可能不够
# System,DUP: total=8.00MiB, used=16.00KiB
# 3. 检查配额
sudo btrfs qgroup show /data 2>/dev/null | grep -v "none"
# 4. 检查设备统计
sudo btrfs device stats /data
# 5. 检查是否有 balance 在运行
sudo btrfs balance status /data
14.2.4 解决方案
方案 1:Balance 回收空间
# 先取消可能挂起的 balance
sudo btrfs balance cancel /data 2>/dev/null || true
# 渐进式 balance
sudo btrfs balance start -dusage=5 /data
sudo btrfs balance start -dusage=10 /data
sudo btrfs balance start -dusage=20 /data
# 元数据 balance
sudo btrfs balance start -musage=5 /data
sudo btrfs balance start -musage=10 /data
方案 2:清理快照
# 列出所有快照
sudo btrfs subvolume list -s /data
# 删除旧快照
sudo btrfs subvolume delete /data/@snapshots/old-*
# 或使用 snapper 清理
sudo snapper cleanup timeline
sudo snapper cleanup number
方案 3:禁用配额
# 如果配额导致问题
sudo btrfs quota disable /data
方案 4:添加设备扩展
# 添加新设备
sudo btrfs device add /dev/sdc /data
# 立即 balance
sudo btrfs balance start /data
方案 5:紧急空间释放
# 删除不需要的文件
sudo find /data -type f -name "*.tmp" -delete
sudo find /data -type f -size +100M -mtime +30 -delete
# 清空已删除但仍被进程占用的文件
sudo lsof +L1 /data
14.3 只读文件系统
14.3.1 问题描述
# 文件系统变为只读
$ touch /data/testfile
touch: cannot touch '/data/testfile': Read-only file system
# 查看挂载状态
$ mount | grep /data
/dev/sdb1 on /data type btrfs (ro,relatime)
14.3.2 原因
| 原因 | 说明 |
|---|---|
| 设备 I/O 错误 | 磁盘故障或连接问题 |
| 内核检测到损坏 | 数据或元数据校验和错误 |
| 空间完全耗尽 | enospc 后转为只读 |
| 手动只读挂载 | mount -o ro |
14.3.3 诊断
# 1. 检查内核日志
dmesg | tail -50 | grep -i btrfs
# 常见错误信息:
# BTRFS error (device sdb): bdev /dev/sdb errs: wr 5, rd 0, flush 1, corrupt 0
# BTRFS: error (device sdb) in btrfs_commit_transaction:...
# 2. 检查设备统计
sudo btrfs device stats /data
# 3. 检查空间
sudo btrfs filesystem usage /data
14.3.4 恢复方法
方法 1:重新挂载为读写
# 如果只是临时问题
sudo mount -o remount,rw /data
方法 2:修复设备错误后重新挂载
# 修复设备错误(可能需要更换磁盘)
# ...
# 重新挂载
sudo umount /data
sudo mount /dev/sdb1 /data
方法 3:使用 rescue 选项挂载
# 使用备份的根节点挂载
sudo mount -o rescue=usebackuproot /dev/sdb1 /data
# 使用所有救援选项
sudo mount -o rescue=usebackuproot,nologreplay,skipbalance /dev/sdb1 /data
方法 4:降级模式挂载(RAID)
# RAID 1 模式下,如果一个设备故障
sudo mount -o degraded /dev/sdb1 /data
# 然后替换故障设备
sudo btrfs replace start /dev/sdc /dev/sdd /data
14.4 设备故障处理
14.4.1 检测设备故障
# 检查设备错误统计
sudo btrfs device stats /data
# [/dev/sdb].write_io_errs 0
# [/dev/sdb].read_io_errs 0
# [/dev/sdb].flush_io_errs 5 ← 非零值表示问题
# [/dev/sdb].corruption_errs 0
# [/dev/sdb].generation_errs 0
# 检查 SMART 状态
sudo smartctl -a /dev/sdb
# 内核日志中的设备错误
dmesg | grep -i "error\|fail\|btrfs"
14.4.2 单设备模式处理
# 单设备(无 RAID)故障时:
# 1. 立即备份可读数据
sudo mount -o degraded,ro /dev/sdb1 /mnt/rescue
sudo rsync -av /mnt/rescue/ /backup/
# 2. 尝试修复
sudo umount /mnt/rescue
sudo btrfs check --repair /dev/sdb1 # ⚠️ 危险
# 3. 尝试恢复
sudo btrfs restore /dev/sdb1 /recovery/
14.4.3 RAID 模式处理
# RAID 1 设备故障处理:
# 1. 文件系统自动进入降级模式
sudo btrfs filesystem show /data
# devid 1 size 100.00GiB used 12.00GiB path /dev/sdb
# devid 2 size 0.00B used 0.00B path /dev/sdc ← 故障设备
# 2. 替换故障设备
sudo btrfs replace start /dev/sdc /dev/sdd /data
# 3. 等待替换完成
sudo btrfs replace status /data
# 4. 验证
sudo btrfs device stats /data
sudo btrfs scrub start /data
14.5 数据恢复
14.5.1 btrfs restore
# 从损坏的文件系统恢复数据
# btrfs restore 只读取数据,不修改原文件系统
# 恢复所有数据
sudo btrfs restore /dev/sdb1 /recovery/
# 恢复特定子卷
sudo btrfs restore -r 256 /dev/sdb1 /recovery/
# 忽略错误继续恢复
sudo btrfs restore -i /dev/sdb1 /recovery/
# 恢复符号链接
sudo btrfs restore -S /dev/sdb1 /recovery/
# 恢复快照
sudo btrfs restore -s /dev/sdb1 /recovery/
# 指定根节点偏移(高级用法)
sudo btrfs restore -t <bytenr> /dev/sdb1 /recovery/
14.5.2 btrfs check –repair
# ⚠️ 警告:--repair 可能导致数据丢失!
# 只在其他方法都失败时才使用
# 1. 先只读检查
sudo btrfs check /dev/sdb1
# 2. 如果 check 报错,尝试修复
sudo btrfs check --repair /dev/sdb1
# 3. 特定修复选项
sudo btrfs check --init-extent-tree /dev/sdb1 # 修复 extent 树
sudo btrfs check --clear-space-cache v1 /dev/sdb1 # 清除 v1 空间缓存
sudo btrfs check --clear-space-cache v2 /dev/sdb1 # 清除 v2 空间缓存
14.5.3 数据恢复流程
发现故障
│
▼
┌───────────────┐
│ 1. 停止写入 │ (卸载或 remount ro)
└───────┬───────┘
│
▼
┌───────────────┐
│ 2. 备份镜像 │ (dd if=/dev/sdb of=/backup/sdb.img)
└───────┬───────┘
│
▼
┌───────────────┐
│ 3. btrfs check│ (只读检查)
└───────┬───────┘
│
├─ 无错误 → 重新挂载使用
│
▼
┌───────────────┐
│ 4. btrfs │ (尝试恢复)
│ restore │
└───────┬───────┘
│
├─ 成功 → 从恢复的数据重建
│
▼
┌───────────────┐
│ 5. check │ (最后手段)
│ --repair │
└───────┬───────┘
│
▼
从备份重建
14.6 内核 Panic 与 Btrfs
14.6.1 常见 Panic 原因
| 原因 | 说明 |
|---|---|
| 内核 bug | Btrfs 代码中的 bug |
| 硬件故障 | 内存或磁盘控制器故障 |
| 空间耗尽 | 严重 enospc 导致内核 panic |
| 驱动不兼容 | 存储驱动或文件系统模块问题 |
14.6.2 恢复步骤
# 1. 从 Live CD/USB 启动
# 2. 检查文件系统
sudo btrfs check /dev/sdb1
# 3. 尝试使用备份根节点挂载
sudo mount -o rescue=usebackuproot /dev/sdb1 /mnt
# 4. 如果仍然失败
sudo btrfs restore /dev/sdb1 /recovery/
# 5. 收集日志用于 bug 报告
# /var/log/kern.log 或 journalctl
14.7 故障排查工具
14.7.1 诊断命令速查
| 命令 | 用途 |
|---|---|
btrfs filesystem show | 文件系统概览 |
btrfs filesystem df | 空间使用详情 |
btrfs filesystem usage | 空间使用分析 |
btrfs device stats | 设备错误统计 |
btrfs scrub status | 校验状态 |
btrfs balance status | 平衡状态 |
btrfs subvolume list | 子卷列表 |
btrfs check | 文件系统检查 |
btrfs restore | 数据恢复 |
dmesg | 内核日志 |
smartctl | 磁盘 SMART 状态 |
14.7.2 日志分析
# Btrfs 相关内核日志
dmesg | grep -i btrfs
# 常见日志模式:
# 1. 校验和错误
# BTRFS warning (device sdb): csum error ino 257 off 0 csum 0x1234 expected 0x5678
# 2. 设备 I/O 错误
# BTRFS error (device sdb): bdev /dev/sdb errs: wr 5, rd 0, flush 1
# 3. 空间不足
# BTRFS warning (device sdb): block rsv returned -28
# 4. 只读转换
# BTRFS error (device sdb): commit aborted: -5
14.8 本章小结
| 故障 | 解决方案 |
|---|---|
| enospc (空间不足) | balance 回收 / 清理快照 / 添加设备 |
| 只读文件系统 | 检查设备错误 / rescue 挂载 / 替换设备 |
| 设备故障 (RAID) | btrfs replace 替换 |
| 设备故障 (单设备) | btrfs restore 恢复数据 |
| 数据损坏 | scrub 发现 / RAID 自动修复 |
| 挂载失败 | rescue=usebackuproot / btrfs check |
排查流程:
- 查看
dmesg日志 - 检查
btrfs device stats - 检查
btrfs filesystem usage - 根据错误类型选择修复方案