记一次群晖NAS的BTRFS出现Checksum Mismatch的问题探索
现象
在群晖日志中心可以看到有很多Checksum mismatch on file的警告。群晖对此的解决方案如下:
https://kb.synology.cn/zh-cn/DSM/tutorial/Btrfs_checksum_mismatch
可以基本说是这些文件的部分数据块必定丢失了。如果还能自动修复,它就不会出现这个警告,会静默修复。如果数据很重要,需要自己提前定期冷备,定期执行群晖存储空间的数据清理。
细节探索
日志的错误信息从何而来?
目前了解到的途径有2种:
- 在程序正常读取一个文件时,btrfs校验文件失败并且无法修复时也会往dmesg输出
- 在数据清理过程中,btrfs无法修复损坏的文件时,会往dmesg输送特定信息,DSM捕获并转为日志输出
dmesg中可以看到类似如下的信息:
BTRFS: (null) at logical 3914661879808 on dev /dev/mapper/cachedev_0, sector 7807321072, root 1342, inode 19862, offset 462848, length 319, links 1 (path: 手机相册2/图集/@eaDir/170.jpg/SYNOPHOTO_THUMB_XL.jpg)
Btrfs如何修复
dmesg中记录的修复过程的日志。
BTRFS warning (device dm-1): csum failed ino 19862 off 438272 csum 643678506 expected csum 2029431650
解读第一行:首先有上层的程序在读取inode为19862的文件,文件系统btrfs发现这个文件的第438272个数据块的校验和是643678506,不是预期的2029431650,因此触发了修复流程。一个Btrfs数据块大小通常是4KB。紧接着开始了修复流程,[Self Heal]开头的相关日志。
- 列出了这个数据库的副本所在的分区,有2个:d-disk和p-disk,分别存在sda5和sdd5。
- 尝试选择了第一个d-disk分区
- 对该分区做校验发现结果还是一样是643678506不是2029431650,进入下一轮重新选择副本流程
- 选择了第二个p-disk分区
- 再做一次校验,结果还是一样
- 放弃修复。
定位出错的inode是哪个文件
- 操作系统上层命令
find /path -inum xxx
- 打印btrfs文件树
错误的校验码在出错的文件中都一样
通篇搜索dmesg日志,可以发现出错的校验码都是643678506,把其中一个文件拷贝出来观察C其二进制。
如上诉日志信息:
BTRFS warning (device dm-1): csum failed ino 19862 off 438272 csum 643678506 expected csum 2029431650
偏移量438272转为十六进制是0x6b000。使用VSCode打开,并使用微软的HexEditor扩展插件,随后Ctrl+G定位到偏移地址处。
可以发现,虽然左右2个文件偏移地址不一样,但是出错的这一4KB块的内容都是一样的,左边从0x6b000到0x6c000之前;右边文件从0开始到1000之前,甚至1000到2000也是一个出错的块。都是241A 9C92 6D85 CE6D …… 开头。
这块数据的内容大概可能是硬盘固件对于无法读取的扇区给出的默认数据块,具体原因仍无法得知。