如何检索底层块设备 IO 错误

Posted

技术标签:

【中文标题】如何检索底层块设备 IO 错误【英文标题】:How to retrieve underlying block device IO error 【发布时间】:2019-01-09 14:12:55 【问题描述】:

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

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

【问题讨论】:

您是否正在寻找超出返回值 (errno) 的内容? man7.org/linux/man-pages/man2/lseek.2.html 当然,errno 等于 EIO,就像这里man7.org/linux/man-pages/man2/read.2.html 然后呢? @kreuzerkrieg 我不相信有办法做到这一点。您应该只检查内核日志。还要检查this。 根据您的链接,看起来像死路一条......我想在过去的十年半里没有任何变化:( 由于逻辑卷、回写和预读,文件读写与设备读写不是 1:1。您必须查找底层内核记录的错误。用户空间程序将永远无法使用它。 【参考方案1】:

您无法从 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中的代码可以看出,这并不容易!

【讨论】:

这就是我现在所拥有的,我希望放弃对 NVMe 不起作用的 sg 东西,并切换到更通用的东西。据我所知,没有这样的事情,所以我会放弃使用块设备并切换到用户模式 ​​NVMe(使用 SPDK)

以上是关于如何检索底层块设备 IO 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何提高Linux下块设备IO的整体性能?

求助SQL Server I/O设备错误

zz`linux块设备IO栈浅析

Linux下驱动开发_块设备驱动开发(内存模拟存储)

操作系统10:IO系统

存储管理--LVM2