最近遇到一条内核消息:
ata3.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata3.00: irq_stat 0x40000008
ata3.00: failed command: READ FPDMA QUEUED
ata3.00: cmd 60/08:00:98:b2:78/00:00:13:00:00/40 tag 0 ncq 4096 in
res 41/40:08:9a:b2:78/00:00:13:00:00/00 Emask 0x409 (media error) <F>
ata3.00: status: { DRDY ERR }
ata3.00: error: { UNC }
ata3.00: SB600 AHCI: limiting to 255 sectors per cmd
ata3.00: SB600 AHCI: limiting to 255 sectors per cmd
ata3.00: configured for UDMA/133
sd 2:0:0:0: [sda] Unhandled sense code
sd 2:0:0:0: [sda] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
sd 2:0:0:0: [sda] Sense Key : Medium Error [current] [descriptor]
Descriptor sense data with sense descriptors (in hex):
72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00
13 78 b2 9a
sd 2:0:0:0: [sda] Add. Sense: Unrecovered read error - auto reallocate failed
sd 2:0:0:0: [sda] CDB: Read(10): 28 00 13 78 b2 98 00 00 08 00
end_request: I/O error, dev sda, sector 326677146
ata3: EH complete
我设法纠正了错误,并详细描述了我用来修复磁盘的复杂过程。然后懒得发布它(我想这个周末我会发布)。
我现在想做的是创建一些程序来自动化该过程。为此,我需要“捕获内核错误”。
我所说的陷阱是指: 1) 终止导致错误的系统调用。我注意到,很多时候像这样的错误会导致硬盘挂起,即忽略来自其他系统命令调用的请求,直到该进程运行完毕。通常会导致其他调用返回错误。通过诊断程序,这将导致错误的操作被识别为罪魁祸首。
2)向调用进程发送某种信号,让它知道它是罪魁祸首。
建议?
答案1
“导致”它的程序(实际上,它是由坏硬件引起的,更合适地说“是它的受害者的程序”)甚至可能不再存在。
例如,发送一个写入,然后退出。写操作将保留在内核缓冲区中,直到内核执行写回。此时可能会发生 I/O 错误。
当节目做仍然存在,它已经被告知错误。例如,read
将设置errno
为EIO
。 (此错误也可能来自write
、fsync
、fdatasync
、 甚至close
。)
它花费永远的原因与内核无关,完全是驱动器。驱动器花费一段时间重试读取,看看是否可以理解损坏的扇区。如果您不希望这样做(例如,因为您在 RAID 上运行,并且只是将扇区重新安排到磁盘的镜像),您可以尝试使用 smartctl 更改 SCT 错误恢复控制设置。请注意,许多非企业磁盘不支持此功能。
除了 RAID(或类似)的情况外,没有办法自动修复它。数据已丢失。内核无法修复这个问题。
如果您正在运行 Linux 软件 RAID (mdraid),即使使用的是半新的内核,mdraid 也会通过从镜像读取错误扇区来自动修复它,然后将正确的扇区写回有读取错误的驱动器。
如果您在写代替读,然后更换驱动器。
(顺便说一句:READ FPDMA QUEUED 不是错误。它只是 (S)ATA 命令失败。“Medium Error”才是错误。)