5
21
2016
16

当 SSD 坏掉之后

本文来自依云's Blog,转载请注明。

某天,我注意到系统日志中有如下报错:

ata2.00: exception Emask 0x0 SAct 0x80 SErr 0x0 action 0x0
ata2.00: irq_stat 0x40000008
ata2.00: failed command: READ FPDMA QUEUED
ata2.00: cmd 60/18:38:64:ad:96/00:00:00:00:00/40 tag 7 ncq 12288 in
         res 41/40:00:64:ad:96/00:00:00:00:00/00 Emask 0x409 (media error) <F>
ata2.00: status: { DRDY ERR }
ata2.00: error: { UNC }
ata2.00: configured for UDMA/133
sd 1:0:0:0: [sdb] tag#7 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x08
sd 1:0:0:0: [sdb] tag#7 Sense Key : 0x3 [current] [descriptor] 
sd 1:0:0:0: [sdb] tag#7 ASC=0x11 ASCQ=0x4 
sd 1:0:0:0: [sdb] tag#7 CDB: opcode=0x28 28 00 00 96 ad 64 00 00 18 00
blk_update_request: I/O error, dev sdb, sector 9874788
bcache: bch_count_io_errors() sdb1: IO error on reading dirty data from cache, recovering
ata2: EH complete

啊,看来我的 SSD 要坏掉了么?!拿 bcache-status 看了一下状态,已经500多个报错了,但是我并没有遇到什么问题。看了一下 SSD 的 SMART 信息,也是500多个报错。这种报错出现已经有几天了,但是似乎影响并不大?SMART 报告也说「状况正常」。那就等有时间再处理好了,先把 bcache 缓存策略从「writeback」改成「writethrough」好了。我当时是这么想的。

出事的 SSD 是笔记本自带的,16G,被我用作缓存了。使用的是 bcache,一年之前我写文章讲过的。没想到刚刚一年,就开始出问题了。

过了一两天之后。我正上班中,同步 MediaWiki 数据时发现自己的机器又连不上了。我起初以为是网络问题,因为我记得很清楚我的机器是开着的。但是过了一会儿它还是不能访问。我 ping 了一下,却发现是通的!登陆到我作为路由器的树莓派上却发现,网络是正常的。能 ping 通笔记本,但是从树莓派上也 ssh 不了,访问 nginx 也没回应。所以笔记本还在线,但是系统出问题了。奇怪的是,访问另一端口上我用 Tornado 写的 Web 程序时却是正常的。

终于等到了下班。回到家里之后就听见笔记本风扇呼呼地响着。赶紧打开查看。htop 显示 journald 正在使用 CPU。于是去看 journald 日志,心里顿时凉了半截:日志只记录到上午,但满是上边那样的 SSD 报错。进一步的检查发现,/ 分区已经被挂载为只读,syslog-ng 日志比 journald 日志记录了更多的报错。火狐已经不知道什么时候挂掉了,并且启动不了。sudo 还是好的,但是运行 zsh 时会段错误。运行 bash 的话,会报一点错,可以看到有些文件已经变成无意义的数据了。bash 能启动,但是很奇怪的是,输入不了字符 e……想起还装了 dash,于是用这个连最基本的补全都没有的 shell,配合还没有挂掉的连着 VPS 的 mosh 上的 IRC 上网友们的帮助,尝试禁用 SSD 缓存。

结果是失败了。关于 bcache 有些资料与我看到的情况并不一致。重启会报一些错,然后我进入了 initramfs 里的 shell,尝试禁用 SSD,依旧失败中,脏数据写不回去,所以禁用不了缓存……不过看到了缓存中脏数据只有几百K。当然单位是什么我就不知道了……

放弃。又一天,我改从救援系统进入。记得有个工具能把普通分区转成 bcache。手机上网找到了,blocks。但是它并不能把 bcache 转回来。好在是开源项目,我读了一下代码,结合别人的说法,结论是:把普通分区转为 bcache,只要把分区缩小,在起始处空出一点空间,然后写入 bcache 的超级块就可以了。于是反过来,只要跳过 bcache 的超级块来读,就可以读到原来的分区数据了。

但是,bcache 超级块有多大呢?不知道。不过之前看到过一个扫数据的脚本,用类似的办法找一下分区数据的位置好了:

for i in {1..20}; do dd if=/dev/sda2 skip=$i | file -; done

file 显示在第8块的地方发现了「LUKS encrypted file」。这就是我要找的文件系统了!

为保险起见,先读读看。使用 losetup 把 /dev/sda2 映射成只读的 loop 设备,但是跳过开头的 8192 字节(dd 的块是 512 字节一个)。然后用 cryptsetup 解密。解密成功了。只读挂载解密之后的 ext4 文件系统。挂载成功了。看了一下内核日志,没有报错,没有警告。chroot 进去,正常,没有段错误,配置文件没有变成无意义的乱码。一切进行得好顺利!损坏程度比我以为的要轻不少呢!

为了确认损坏情况,我进行了一次模拟备份,也就是 rsync 的「--dry-run」选项。这样与最近的一次备份作比较,看看差异。结果很乐观,rsync 只报了十来个 I/O 错误。不过这也说明文件系统还是有问题的。

又一天。开始恢复系统了。还是从救援系统进入。进入 gdisk,删除原来的 sda2 分区,新建一个小了 8192 字节的分区。经验表明这样子删掉再重建分区表是没有问题的。也确实没出什么问题。不带 bcache 的文件系统出来了。解密之,然后使用 fsck 修复。修复过程中,fsck 问了我一大堆是不是要修复的问题。修复完毕之后,更改内核选项以便适应新的分区表,重启。

一切正常。不过根据之前 rsync 和修复过程中提到的文件名,去看了一下那些文件。都是最近更新系统时的一些 Python 文件。有一些文件消失了,另一些文件的权限和类型变得很奇怪。删掉,重装安装对应的软件包。完事了~不过没有了 SSD 缓存,能够感觉到有些操作会慢不少。

这 SSD 也真容易坏啊。刚刚一年呢。而且坏的过程很快,预警期只有几天。现在 SMART 报告已经出现过1000多个错误了,但整体评估还是「磁盘状况正常」……

好在我用的都是自由软件,虽然可能找遍整个互联网都没有个说法,但是还有实现它们的源码可以阅读,可以自己去思考解决方案。当然啦,就算这个 bcache 完全坏掉了,我也不需要太惊慌,因为我有备份嘛,更麻烦,但最多只损失几天的数据,不会突然之间什么都没有了。

Category: Linux | Tags: linux 数据恢复 bcache | Read Count: 7958
谷月轩 说:
May 21, 2016 11:58:42 PM

百合的博客换新主题啦!

kit393 说:
May 22, 2016 12:00:16 AM

有意思的文章。很有启发。

Haowu Ge 说:
May 22, 2016 09:37:56 PM

大神好厉害,都会数据恢复了

jiazhoulvke 说:
May 23, 2016 05:13:20 PM

我的ssd昨天也出问题了。我的笔记本被泼了一罐可乐,我就马上关机了,用吹风机吹干以后再开机就进不了系统了,貌似是强制关机导致硬盘受损。不过还好fsck能修复。ext4好容易坏啊。

Avatar_small
依云 说:
May 23, 2016 07:34:21 PM

你这是软件导致的损坏,和我的 SSD 的状况不一样的啦。

ext4 还好啦。学生时代我见到过同学的 NTFS 动不动就坏掉的。reiserfs 也比 ext4 容易坏,写操作时强制关机必然需要手动 fsck 的。我的 ext4 在各种关机的情况下都没有出现过需要手动 fsck 的情况呢。

我的笔记本是防泼溅的呢。

Avatar_small
依云 说:
May 23, 2016 07:35:06 PM

不换不行啊。那个主题我很喜欢,但是侧栏就是出不来 :-(

jiazhoulvke 说:
May 23, 2016 08:04:17 PM

依云时刻不忘黑一下M$,

自由建客 说:
May 23, 2016 09:39:09 PM

SSD 用作缓存,写入次数能不多吗?

XSign 说:
May 26, 2016 12:59:40 PM

LUKS...有奸情.....

vinoca 说:
May 29, 2016 04:53:40 PM

上月SSD坏了一块...

Icenowy Zheng 说:
Jun 21, 2016 08:06:22 AM

其实你可以把分区前几块 dd 出来然后 binwalk
(然而维修环境大概没有 binwalk 吧

Avatar_small
依云 说:
Jun 21, 2016 10:27:45 AM

嗯,之前只听过 binwalk 没用过。不过可以装的,官方源里有呢。不过是在 [community] 里,稍微有点麻烦。

Icenowy Zheng 说:
Jun 21, 2016 12:23:16 PM

binwalk 爬 binary 文件的内嵌数据什么的挺有用的

TJM 说:
Jul 14, 2017 03:51:36 PM

我的SMART表示sdb一切良好尽管dmesg里一大堆报错……
话说sector 216~sector 231跪了有办法屏蔽吗?
我不是很懂为啥linux内核在启动的时候要读这几个sectors。
我的GPT header+entries一共就用了前三个sector
第一个分区是从sector 2049开始的
所以安装GPT标准sector 4~sector 2048应该都是0
而且那些可读的sectors也确实都是0
所以sector 216~sector 231也应该是0
所以我更不解linux内核为什么要去读他们了(
我很好奇能不能通过内核command line让内核只读前三个sectiors……

TJM 说:
Jul 14, 2017 03:52:56 PM

s/安装/按照/

Avatar_small
依云 说:
Jul 14, 2017 04:59:14 PM

不知道……我没怎么遇到过磁盘坏掉的情况,这一次坏掉的就16G,所以坏了也就坏了(后来放了一段时间之后它又能用了)。

SMART 好像就那个性,明明出错了它还说良好……


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

部分静态文件存储由又拍云存储提供。 | Theme: Aeros 2.0 by TheBuckmaker.com