如何检索底层块设备 IO 错误
How to retrieve underlying block device IO error
考虑系统中的一个设备,/dev/hdd[sg][nvme]xx下的东西
打开设备,获取文件描述符并开始使用它(read(v)
/write(v)
/lseek
,等等),有时您可能会得到 EIO
。您如何检索设备驱动程序报告的底层错误?
EDIT001:如果无法使用 unistd
函数,也许还有其他方法可以使用块设备来提供更多低级信息,例如 sg_scsi_sense_hdr
?
您无法从 POSIX 函数中获取更多错误详细信息。不过,您已经走上了 SCSI 通用内容的正确轨道。但是,男孩,它装满了头发。查看 sg3_utils 中关于如何执行 SCSI READ(16) 的示例。这样回来的时候可以让你看看sense数据:
https://github.com/hreinecke/sg3_utils/blob/master/examples/sg_simple16.c
当然,此技术不适用于 NVMe 驱动器。 (至少,据我所知)。
我过去玩过的一个概念是使用正常的 POSIX/libc 块 I/O 功能,如 pread
和 pwrite
直到我得到一个 EIO。那时,您可以引入 SCSI 通用版本来尝试弄清楚发生了什么。在理想情况下,pread
或 lseek/read
因 EIO 而失败。然后您转身并使用 SG READ (10) 或 (16) 重新发行它。如果这不仅仅是暂时性故障,这可能 return 检测到您的应用程序可以使用的数据。
这是一个例子,使用命令行 sg_read 程序。我有一个正在读写的 iSCSI 连接磁盘。在目标上,我删除了它的 LUN 映射。 dd
报告 EIO:
# dd if=/dev/sdb of=/tmp/output bs=512 count=1 iflag=direct
dd: error reading ‘/dev/sdb’: Input/output error
但是 sg_read
报告了一些更有用的信息:
[root@localhost src]# sg_read blk_sgio=1 bs=512 cdbsz=10 count=512 if=/dev/sdb odir=1 verbose=10
Opened /dev/sdb for SG_IO with flags=0x4002
read cdb: 28 00 00 00 00 00 00 00 80 00
duration=9 ms
reading: SCSI status: Check Condition
Fixed format, current; Sense key: Illegal Request
Additional sense: Logical unit not supported
Raw sense data (in hex):
70 00 05 00 00 00 00 0a 00 00 00 00 25 00 00 00
00 00
sg_read: SCSI READ failed
Some error occurred, remaining block count=512
0+0 records in
在上面的输出中可以看到Logical unit not supported
额外的感知代码,说明目标处没有这样的LU。
可能吗?是的。但是从sg_simple16.c
中的代码可以看出,这并不容易!
考虑系统中的一个设备,/dev/hdd[sg][nvme]xx下的东西
打开设备,获取文件描述符并开始使用它(read(v)
/write(v)
/lseek
,等等),有时您可能会得到 EIO
。您如何检索设备驱动程序报告的底层错误?
EDIT001:如果无法使用 unistd
函数,也许还有其他方法可以使用块设备来提供更多低级信息,例如 sg_scsi_sense_hdr
?
您无法从 POSIX 函数中获取更多错误详细信息。不过,您已经走上了 SCSI 通用内容的正确轨道。但是,男孩,它装满了头发。查看 sg3_utils 中关于如何执行 SCSI READ(16) 的示例。这样回来的时候可以让你看看sense数据:
https://github.com/hreinecke/sg3_utils/blob/master/examples/sg_simple16.c
当然,此技术不适用于 NVMe 驱动器。 (至少,据我所知)。
我过去玩过的一个概念是使用正常的 POSIX/libc 块 I/O 功能,如 pread
和 pwrite
直到我得到一个 EIO。那时,您可以引入 SCSI 通用版本来尝试弄清楚发生了什么。在理想情况下,pread
或 lseek/read
因 EIO 而失败。然后您转身并使用 SG READ (10) 或 (16) 重新发行它。如果这不仅仅是暂时性故障,这可能 return 检测到您的应用程序可以使用的数据。
这是一个例子,使用命令行 sg_read 程序。我有一个正在读写的 iSCSI 连接磁盘。在目标上,我删除了它的 LUN 映射。 dd
报告 EIO:
# dd if=/dev/sdb of=/tmp/output bs=512 count=1 iflag=direct
dd: error reading ‘/dev/sdb’: Input/output error
但是 sg_read
报告了一些更有用的信息:
[root@localhost src]# sg_read blk_sgio=1 bs=512 cdbsz=10 count=512 if=/dev/sdb odir=1 verbose=10
Opened /dev/sdb for SG_IO with flags=0x4002
read cdb: 28 00 00 00 00 00 00 00 80 00
duration=9 ms
reading: SCSI status: Check Condition
Fixed format, current; Sense key: Illegal Request
Additional sense: Logical unit not supported
Raw sense data (in hex):
70 00 05 00 00 00 00 0a 00 00 00 00 25 00 00 00
00 00
sg_read: SCSI READ failed
Some error occurred, remaining block count=512
0+0 records in
在上面的输出中可以看到Logical unit not supported
额外的感知代码,说明目标处没有这样的LU。
可能吗?是的。但是从sg_simple16.c
中的代码可以看出,这并不容易!