btrfs parent transid verify error的玄学修复记录
错误排查
小伙伴大半夜找我说暗影大人的视频无法播放了,我去确认了一下,jellyfin转码烧录mks字幕确实出问题了,但是让客户端不转码直接本地播放是可以播放的,就没在意,直到第二天一觉醒来,他又来说问题了,这次不是视频无法播放,而是jellyfin打不开了
我第一反应是ddns寄了,或者我路由网络又出毛病了(
昨晚才处理好的Clash DNS解析啊),但是一个测试发现并没有,只是所有web服务都无法访问了,ssh看了下docker,好家伙docker寄了好端端的docker怎么会寄,考虑到docker容器所在的分区曾经寄过,我dmesg看了下,嗯,磁盘分区寄了,症状和上次类似,只是这一次寄得更彻底了。
首先,寄了的问题磁盘分区是ArchLinux上的sdb1
:
|
|
而这是dmesg
记录的一部分日志,因为这是事后回忆整理,我留下的记录并不是很多,悲
|
|
尝试找到错误文件
可以看到错误首先是114737152
这个inode对应的文件校验错误,那么首先应该找到它,好在分区虽然寄了,但是因为forced readonly
所以依旧能挂载并且可读,先一个find ./ -num 114737152
尝试找到它,结果并没有像以前寄的时候那样找到对应的文件,而是直接打印了一大堆的报错
|
|
通过btrfs工具查看错误
btrfs虽然是以不成熟和不稳定且性能一般闻名于世,不过还是提供了一些工具来尝试解决常见问题
通过谷歌搜索,我找到了一个类似问题的疑难解答页面,本来以为是人家单独列出来肯定是常见好救的,结果它建议我备份数据,这是一个永久性错误,并且原因不明
这不能够啊!
这个文档里虽然没有提供任何修复方案,但是记录了btrfs的各种命令用法,倒也不算没有一点用处
确认一下btrfs记录到多少个错误
btrfs dev stats /dev/sdb1
跑一下,上一次分区错误的时候,这里记录了几百个错误,但是没有处理好,我最后格式化分区了,出乎意料的,这次一个错误都没有发现
|
|
虽然不知道这意味着什么,但没有错误记录,也许还有救,在网上找一找前人的经验,比方说StackOverflow上的帖子
尝试usebackuproot
按照帖子里的一个答案,只读挂载时带上
usebackuproot
:mount -t btrfs -o ro,usebackuproot /dev/sdb1 /home/cache
如果能够成功挂载,则去掉只读的ro
重新挂载,能挂载上说明修复了
我尝试只读挂载成功并没有问题,毕竟我本来就能只读挂载,此时再次进入/home/cache
目录尝试读取文件,依旧是Input/output error
,抱着侥幸心理,我尝试不指定只读挂载,即mount -t btrfs -o usebackuproot /dev/sdb1 /home/cache
,不出意料的发生了错误,但是错误信息我没保留下来,所以没法展示了
格式化前的死马当活马医
前文说过,我这个分区不是第一次出现这种错误,上一次我尝试了各种btrfs的命令也没修复成功,但成功把数据给备份出来了 而这一次我讲数据复制出来都会发生错误,其实并没有什么动力去研究,毕竟有一次失败在前,而且这次连备份都做不到,甚至产生放弃btrfs,格式化回ext4的想法
就在我即将运行mkfs.ext4 /dev/sdb1
时,我突然想到这次btrfs dev stats
并没有报错,虽然出现了上次没有出现的Input/output error
,但是btrfs本身的情况也许没那么糟糕,上次用过的命令可以试试
btrfs
有不少的子命令工具可以做一些诸如重建树或者擦除
先跑一个btrfs scrub status /home/cache
看看结果
|
|
没有错误
btrfs有一个不建议使用的命令可以尝试修复错误,即
btrfs check --repair /dev/sdb1
,我上一次也执行过,但并没有修复我的问题
但这次既然没有错误,也就是有尝试的价值
直接运行btrfs check --repair --force /dev/sdb1
,果然跟上一次什么变化都没有的输出不同,它输出了很多修复节点的信息,也没有保存下来
运行完成之后,我尝试可读写挂载,问题依旧
峰回路转
失望也带着绝望,我只能格式化了,并且这次格式化我不打算再使用btrfs了,它已经两次在同一个分区上寄了,mkfs.ext4 /dev/sdb1
,跟数据和btrfs说拜拜吧 其实我挂载的路径是cache就说明了没有什么重要数据,仅仅是缓存分区,随便格的那种
出乎意料的,格式化没有开始,设备繁忙中
我确认了一下,我已经卸载设备了,并没有挂载到目录,btrfs dev stats
也显示设备被占用
也许是check占用了设备没有释放,此时的我也没有心情去关心了,只想快点格了然后重建docker容器恢复服务
关闭docker服务开机自启,关闭systemd的开机自动磁盘挂载,重启设备一气呵成
开机之后,我正要格式化,又想,也许它好了呢?
于是我只读挂载了一下,正常挂载,甚至执行ls
的时候都没有Input/output error
了,并且dmesg
也没有任何错误信息,我心情有点小激动,二话不说systemctl start docker
,看看docker能起来不,起不来,依旧是报错,报错信息我都懒得看了
等会,我现在是只读挂载,docker怎么可能起来!!
改成可读写挂载,docker启动了!!服务上线了!!
后续
访问一下jellyfin,发现页面有了,但登录页打不开,F12
看一下原因,少了一个js文件,直接重建容器,一切都正常了,也许btrfs check --repair
给我移除了无法通过校验的文件
准确说我不清楚我是怎么修复的,我只能靠回忆记录下这个并没有多少操作的过程,其中我如果有那么一次没有想再看看分区是不是好了,或者check之后设备不是繁忙中,我恐怕不敢相信我居然能看到它恢复正常,这大概就是不放弃吧(bushi