我了解错误纠正是什么以及它是如何工作的,我想知道的是,当驱动器的固件正在读取数据并偶然发现一个包含足够信息来纠正它的损坏扇区时,除了向操作系统提供正确的数据之外,它是否也将正确的数据写回到该扇区?
偶尔让操作系统读取整个驱动器以期防止此类错误在很长一段时间内累积是否有意义?因为它们可能会定期得到纠正,以避免达到实际故障的阈值。
人们不禁要问,一个完好无损的硬盘是否会因为不可控的外部因素而出现坏扇区,从而变得不可信。希望这样的“清理”可以防止这种情况发生。
例如:
dd if=/dev/sda of=/dev/null bs=32M iflag=direct status="progress"
我的理解是,出于不同的原因,经常会对 RAID 驱动器(或者可能是 RAID 虚拟块设备?)进行类似的事情。
答案1
...它是否也将正确的数据写回到该扇区?
对于我编写固件的控制器,没有。
对于现代 SATA HDD,我猜想无条件重写是不可能的。
首先,这对于读取操作来说是意外的开销,需要额外的时间来完成(即盘片再旋转一圈)。
其次,错误可能是暂时的,可能不会在后续读取时发生。对于这种情况,重写是没有道理的。
第三,无法保证仍可纠正的错误可以变成无错误扇区。最坏的情况是重写会使可纠正性变差,而不是变好。
当然,当发生软错误时,操作系统总是可以选择执行预防措施。
HDD可以选择性地提供重写功能。希捷 SCSI 手册在表 29 中确实提到了“使用 ECC 恢复的数据—数据重写”检测代码,这是“仅供参考,因为本手册涵盖的并非所有驱动器都支持列出的所有代码。”
...您知道如何在 Linux 上访问这些信息吗?
软读取错误被视为成功读取,更正显然在(更详细的)感测数据中报告为“恢复的错误”。
作为内核处理的一部分scsi_io_completion()这以下代码相关:
/*
* Recovered errors need reporting, but they're always treated as
* success, so fiddle the result code here. For passthrough requests
* we already took a copy of the original into sreq->result which
* is what gets returned to the user
*/
if (sense_valid && (sshdr.sense_key == RECOVERED_ERROR)) {
bool do_print = true;
/*
* if ATA PASS-THROUGH INFORMATION AVAILABLE [0x0, 0x1d]
* skip print since caller wants ATA registers. Only occurs
* on SCSI ATA PASS_THROUGH commands when CK_COND=1
*/
if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d))
do_print = false;
else if (req->rq_flags & RQF_QUIET)
do_print = false;
if (do_print)
scsi_print_sense(cmd);
result = 0;
/* for passthrough, *blk_statp may be set */
*blk_statp = BLK_STS_OK;
}
底线:可以记录恢复的错误(或软读取错误)(即是真do_print
的,所以scsi_print_sense()称为),但有些例外情况会导致跳过此日志记录。
此外,SCSI 日志记录可能非常庞大,可能会影响 I/O 吞吐量,因此存储的信息由 SCSI 日志记录级别控制。
一个 bash shell 脚本,scsi_logging_level,可用于访问/修改 Linux SCSI 子系统日志记录级别。
有关 SCSI 日志的更多详细信息,请参阅SCSI 日志记录功能。
是否会有实用程序用于分析硬盘扇区,以便识别诸如您列出的黑名单中的扇区,以防万一?
我不知道。
扫描硬盘的最快方法是使用内置的 SMART 测试。驱动器只读取扇区,不会将数据传输到主机以减慢测试速度。