众所周知,现代硬盘驱动器在固件内部进行坏扇区管理,即当驱动器检测到物理损坏或不可靠的物理扇区时,它会用保留扇区存储中的好扇区替换坏扇区。这种机制消除了操作系统本身进行坏扇区管理的需要。用户可以从名为“重新分配的扇区数”的 SMART 项目中了解扇区替换计数的发展情况。
具有过多重新分配扇区的示例 HDD 驱动器(索引 133 低于阈值 140):
现在我的问题是:HDD固件何时确定应该替换某个扇区。我想象这样的理想情况:
当 HDD 写入扇区时,它会立即读取验证(验证 CRC 校验和并使用 ECC 恢复软错误位)。如果验证失败或固件认为该扇区不可靠,固件可以立即替换该扇区,这样就不会丢失用户数据(至少在写入磁盘表面时不会丢失)。这是一个进行扇区替换的好时机,因为要写入的数据现在肯定保留在硬盘的内部缓存中。驱动器可以尝试尽可能多的“热备用”扇区,直到找到一个好的扇区。
如果我的想法不是事实,那么 HDD 只能在用户下次获取时验证已写入的扇区;但万一下次获取时 CRC 和 ECC 失败,并且其对应的缓存已被丢弃,我们只能知道先前写入的数据已永久丢失。
哪种行为才是事实?有没有网络文章对此进行澄清?
SSD 磁盘应该面临同样的情况,那么 SSD 呢?SSD 的情况似乎更容易理解,因为我很容易想象 SSD 可以在写入后非常快速地进行读取验证;但是,这种方案对于主轴硬盘来说实用吗?似乎 HHD 磁头可以在给定时间内进行读取或写入,因此为了验证写入,它必须等待另一次旋转,直到写入的扇区再次定位在磁头下方 - 这会大大降低数据吞吐量。 - 我很困惑。
答案1
驱动器执行某种形式的写入验证,并且已经这样做了很长一段时间。在驱动器声音很大的旧时代,您可以通过声音判断驱动器是否在坏块上磨损。我无法解释确切的机制,而且我相当肯定确切的方式已经发生了一些变化,因为我们通过各种磁技术。但故障可以在写,该部门将被拉出重新分配池。
您也可以在读取时检测到它,并采用您已确定的故障情况。一些高端 RAID 阵列(当然还有 ZFS)具有后台扫描例程,可在空闲时间读取存储,专门用于查找这些错误。在奇偶校验或镜像 RAID 中,理论上您可以在其他地方获得一份良好的副本,这使得恢复变得容易。
无法编程的 SSD 单元将返回类似的故障状态,并且会从重新分配池中拉出一个新块。磨损的 SSD 单元往往会变成只读状态,因此数据是可以恢复的。实际损坏的单元则是另一回事,就像一点沙砾落在驱动器盘片上一样。
答案2
也许。驱动器可能支持或不支持写入-读取-验证功能集。如果它是类似 ATA 的设备,并且 hdparm 适用于该驱动器,您可以尝试使用以下命令启用写入-读取-验证功能:
sudo hdparm -R1 /dev/sdc
假设驱动器是sdc
。您可以查看lsblk
输出以确定它是哪个驱动器。-R0
禁用它。
如果它告诉您write-read-verify = 2
该功能已启用。
在我的一个 Seagate 7200 rpm 企业级 SATA 硬盘上,它将连续写入性能降低到大约 12MB/秒。您可以预料,启用此功能的硬盘在写入量达到饱和时,写入性能可能会严重下降。
驱动器在实现此功能的方式上具有完全的自由,规范甚至不坚持进行完整的逐字节比较,驱动器可以自由地进行 CRC 校验,如果它愿意的话,甚至可以不进行任何校验,校验是特定于实现的。
驱动器可能会强制执行验证失败导致写入错误,也可能不会。驱动器很可能会实施该功能,因此验证失败会导致写入错误,因为这似乎更符合启用此功能的用户的意图。如果驱动器希望您的写入成功率是铁定的,那么它会在成功写入之前进行验证。我的 Seagate 驱动器似乎就是这样做的。
要验证写入,它必须等待磁盘再次旋转,并等待写入的数据再次经过磁头。每次写入都强制等待旋转会严重降低性能。在 7200 rpm 时,盘片每秒仅旋转 120 次。您至少会定期限制每秒 120 次 I/O。
答案3
每次读取时都会进行验证,因为固件会读取扇区及其 CRC/ECC,如果不适合该扇区,它会尝试重新读取(修复)它。维基百科文章错误检测和纠正仅包含一句话:
现代硬盘使用 CRC 码进行检测和 Reed-Solomon 码来纠正扇区读取中的小错误,并从“损坏”的扇区中恢复数据并将该数据存储在备用扇区中。
但参考资料包含详细解释:
ECC 结构冗余度高达 200 位,每个扇区 256/512 - CRC - 扰码位 - RLL 添加位以引起脉冲和奇偶校验
当数据写入驱动器时,数据会被编码。实际数据本身永远不会被写入,只有数据的解释。如果您认为驱动器包含 0 和 1,那么您的想法是错误的。数据更像是写入驱动器的波形。它必须在输出时重新解释,然后才能变成 0 或 1。在写入数据之前,数据是随机的。这消除了可能相同的模式,以便 ECC 不会混淆。对反复出现的模式进行模式检测很困难。EMI 可以减少,并且对位存储和时序控制的影响较小。
驱动器在放弃之前会尝试几种不同的方法来重新读取数据,其中大多数方法都使用 ECC。如果数据以某种顺序出现,ECC 可能会在某些情况下错误地纠正数据。ECC 读取命令使用至少 3 的 ODD 编号,以免在选择 2 时出现 50/50 的机会。
忽略 ECC 的读取是 LBA 28 命令“长读取”,它在 48 位中被禁用,因为它在 137 GB 以上的驱动器中被确定为过时。137 GB 之后没有可用的读取忽略 ECC。标准尝试是尝试,在大多数硬盘中通常是 10 次尝试。忽略 ECC 读取驱动器可能会导致数据损坏,但有时如果 PCB 出现问题或 ECC 无法正确读取数据,这是获取这些扇区数据的唯一方法。
如果 ECC 编码器确定扇区不可读,则将再次重试该扇区。Reed Solomon 结合扇区重读有望修复 ECC 的数据错误。奇偶校验位被剥离。
和:
写入数据后,将写入 4 字节 ECC 数据块。读取 512 字节后,驱动器将计算 ECC 信息并读取 ECC 数据块并进行比较。如果它们不相等,则驱动器重新读取数据,直到发生超时导致 ECC 数据错误。如果无法重新读取并更正错误,则会导致 UNC 标志表明错误数据无法更正。可以忽略 ECC 进行数据恢复,但您无法验证读取的数据是否正确。这应该作为最后阶段来捕获无法以任何其他方式读取的数据。
因此我得出结论,驱动器不会通过执行额外读取来验证写入操作的数据。但这并不是一场彻底的灾难,因为可以在读取时通过 ECC 修复数据(有时或大多数时候?)。
但最终我们不知道“写入重试”是什么。也许只是写入时由于振动导致磁头错位?或者是物理损坏的扇区根本无法定位?