我有一个 SATA 驱动器,程序总共识别出 8 个坏块badblocks
。据说驱动器固件应该能够重新映射它们并替换备件。我已badblocks
在-n
模式下运行以重写有问题的分区,并多次运行 e2fsck。没有任何变化,始终是相同的 8 个坏块。
当我运行时smartctl
它显示Reallocated_Sector_Ct
at 0
。
如何让固件真正重新映射 8 个坏块?
答案1
如果在整个扇区的写入请求中提供了新数据,则驱动器只能尝试重写或重新分配不可读扇区。badblocks
不这样做,所以没有任何改变。
“非破坏性”读写模式的工作原理如下:
- 读取原始数据
- 编写测试模式
- 读取测试模式
- 写入原始数据
如果第一步已经失败,即无法读取数据,则也无法对该扇区执行写入操作,因为之后无法恢复原始数据。这将是破坏性写入,但您特别要求非破坏性变体,因此尚未完成。
“非破坏性”方法仍然可能因其他原因而无法恢复原始数据,因此无论如何,您都不应该在要保留数据的驱动器上运行坏块。
如果您想badblocks
无论如何都执行此操作,那么您必须使用其-w
写入模式 - 默认情况下会覆盖所有数据,因此您希望将范围缩小到应使用badblocks -w device [last_block [first_block]]
可选参数覆盖的特定扇区范围形式。您可以通过首先运行只读坏块测试来确定这些扇区。
只读测试:
# badblocks /dev/foobar
1000
块 1000 有缺陷,因此专门覆盖该块:
# badblocks -w /dev/foobar 1000 1000
然而,这仍然会失败。为什么?因为badblocks
使用默认的块大小 1024 字节。
对于扇区大小为 512 字节的设备来说这是错误的 — 坏块会覆盖两个扇区而不是一个扇区,从而造成额外的损坏 — 对于扇区大小为 4096 字节的设备来说也是错误的 — 坏块只会写入一个部分扇区,这对于重新分配不起作用因为您必须写入完整的数据块。
因此,对于上面的两个命令,您必须指定驱动器的正确块大小(物理扇区大小)(512 或 4096 或其他)。
随着块大小的改变,报告的块号也会相应改变:
# badblocks -b 512 /dev/foobar
2000
# badblocks -b 4096 /dev/foobar
250
您可以相应地调整写入命令:
# badblocks -b 512 -w /dev/foobar 2000 2000
# badblocks -b 4096 -w /dev/foobar 250 250
这应该使驱动器有机会重新分配有问题的扇区。
如果仍然失败,则还有另一种可能性:如果给定设备是分区或其他逻辑驱动器,并且它未与物理驱动器对齐,则所有写入都将是未对齐的,因此您最终会将 4096 字节写入两个部分 4096 字节扇区。
它不会重新定位目标扇区,而是部分损坏相邻扇区中的数据。
所以这种方法存在一定的导致数据进一步丢失的风险。
答案2
最简单的方法是完全有意地忽略这个问题。
固件将在下次写入时重新映射每个扇区,在此之前无需担心它。
留意其他 SMART 属性。确保您有良好的备份。考虑投资更换磁盘。
答案3
如何让固件真正重新映射 8 个坏块?
您写入损坏的扇区,例如
sudo hdparm --yes-i-know-what-i-am-doing --repair-sector SECTOR_NUMBER /dev/device
这是一种破坏性操作,它将用零 ( ) 替换损坏的扇区0x00
。
SMART 毕竟不是那么“聪明”,我经常看到它失败。即,在大多数情况下,它无法重新分配损坏的扇区,并且需要被告知要做什么。