我正在使用 pxelinux 部署 TinyCore 的内存版本(Linux 版本 4.19.10-tinycore)。它在具有最新 BIOS(截至今天)的 Z270-A 主板上运行。PXE 以传统模式启动。
我编写了一个 Java 应用程序,用于通过网络部署 SSD 映像,并使用 RandomAccessFile 写入它们。我在写入时遇到了奇怪的行为,具体如下:
print_req_error: I/O error, dev sda, sector 42319888
Buffer I/O error on dev sda, logical block 5289986, async page read
ata1: EH complete
ata1.00: Enabling discard_zeroes_data
ata1.00: exception Emask 0x0 SAct 0x40000 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: failed command: READ FPDMA QUEUED
ata1.00: cmd 60/08:90:10:c0:85/00:00:02:00:00/40 tag 18 ncq dma 4096 in
res 41/40:00:10:c0:85/00:00:02:00:00/40 Emask 0x409 (media error) <F>
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
sd 0:0:0:0: [sda] tag#18 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x08
sd 0:0:0:0: [sda] tag#18 Sense Key : 0x3 [current]
sd 0:0:0:0: [sda] tag#18 ASC=0x11 ASCQ=0x4
sd 0:0:0:0: [sda] tag#18 CDB: opcode=0x28 28 00 02 85 c0 10 00 00 08 00
print_req_error: I/O error, dev sda, sector 42319888
Buffer I/O error on dev sda, logical block 5289986, async page read
ata1: EH complete
ata1.00: Enabling discard_zeroes_data
我尝试禁用 NCQ libata.force=noncq
,但无济于事。
奇怪的是,使用我的程序擦除设备dd if=/dev/zero of=/dev/sda bs=1M
然后再次尝试写入数据时不会发生此类错误。看起来用零填充驱动器可以解决问题,但这需要很长时间,并且对设备的健康没有好处。
出于这个原因,我这样实现了写入图像的程序:在写入实际数据之前,先写入零来模拟上述命令。即便如此,错误仍然会发生。
smartctl -a /dev/sda
没有出现任何不良迹象。我已经在多台设备上看到这种情况,例如 Silicon Power S55 和 Micron 1100。这仅有的在此设置中会发生这种情况。在安装的 Ubuntu 18.04 版本中从未发生过这种情况(从磁盘运行,而不是从内存运行)。
内存没有故障,用 memtest 测试过。所有电缆都很好,运行在 Corsair RM1000i 上。
以下是输出消息。我似乎找不到解决这个问题的方法,我现在迷路了。另外,这里是智能控制输出。
编辑:这种情况并不总是发生在同一个扇区。有时它发生在过去运行良好的扇区。这看起来是随机的。
EDIT2:我的程序/dev/sda
作为文件打开并在其上执行 I/O(这是我写入磁盘的方式)
答案1
看起来这些消息确实是假错误。我更改了我的 Java 代码,FileOutputStream
现在使用这个方便的库来代替:http://www.nicecode.eu/java-streams-for-direct-io/
它使用 JNA 提供对文件的本地 I/O 访问,我可以设置 O_DIRECT 标志。我修改了库,将缓冲区从 BLOCK_SIZE(512 字节)增加到 512KB(512*1024)。缓冲区大小必须是块大小的倍数,对于 O_DIRECT 来说,块大小必须是 512 字节。这样,速度就合理了,与 Java 的非本地实现相当。
不再有错误,所有数据均有效(使用 确认md5sum
),无论是对于之前测试过的 Silicon Power SSD 还是新的 Micron SSD。