如何检索基础块设备IO错误

时间:2019-01-09 14:12:55

标签: c++ c linux ioctl block-device

考虑系统中的设备,在/ dev / hdd [sg] [nvme] xx下 打开设备,获取文件描述符并开始使用它(read(v) / write(v) / lseek等),有时您可能会得到EIO。您如何检索设备驱动程序报告的潜在错误?

EDIT001:如果无法使用unistd函数,也许还有其他方法可以与块设备一起使用,这些设备可以提供更多sg_scsi_sense_hdr这样的低级信息?

1 个答案:

答案 0 :(得分:2)

您无法从POSIX函数中获得更多错误详细信息。不过,您将对SCSI通用内容有所了解。但是,男孩,头发满满的。查看sg3_utils中有关如何执行SCSI READ(16)的示例。这将使您在返回时查看感知数据:

https://github.com/hreinecke/sg3_utils/blob/master/examples/sg_simple16.c

当然,此技术不适用于NVMe驱动器。 (至少,据我所知)。

我过去玩过的一个概念是使用普通的POSIX / libc块I / O功能,例如preadpwrite,直到获得EIO。在这一点上,您可以引入SCSI通用版本以尝试找出发生了什么。在理想情况下,preadlseek/read的EIO失败。然后,您转过来使用SG READ(10)或(16)重新发出。如果不只是短暂的故障,这可能会返回您的应用程序可以使用的感知数据。

这是一个使用命令行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中的代码可以看出,这并不容易!