7.8. errno 中报告的错误

使用原始接口,几乎任何字符串都可能被意外地传递给 write(),并可能(但很少)发生一些糟糕的事情。如果检测到某些错误,则很可能 EIO 会被放入 errno 中。

不幸的是,这种情况仍然可能发生在 write() 中,因为它既可以接受原始的 struct sg_header,也可以接受本说明中描述的更新的 sg_io_hdr_t。然而,由于 SG_IO ioctl() 只接受 sg_io_hdr_t 结构,因此随机字符串被解释为命令的可能性较小。由于 sg_io_hdr_t 接口进行了更多的错误检查,它尝试给出更精确的 errno 值,以帮助用户查明问题。[诚然,其中一些 errno 值是从大量可用值中任意选择的。]

在大多数情况下,当对 sg 文件描述符的系统调用失败时,该调用将返回 -1。在应用程序检测到系统调用失败后,它应该读取 "errno" 变量中的值(在执行任何其他系统调用之前)。应用程序应包含 <errno.h> 头文件。

下面是一个 errno 值表,指示哪些对 sg 的调用会生成它们以及错误的含义。write() 调用用 "w" 表示,read() 调用用 "r" 表示,open() 调用用 "o" 表示。

errno    which_calls    Meaning
-----    -----------    ----------------------------------------------
EACCES    <some ioctls> Root permission (more precisely CAP_SYS_ADMIN
                        or CAP_SYS_RAWIO) required. Also may occur during
                        an attempted write to /proc/scsi/sg files.
EAGAIN    r             The file descriptor is non-blocking and the request
                        has not been completed yet.
EAGAIN    w,SG_IO       SCSI sub-system has (temporarily) run out of 
                        command blocks.
EBADF     w             File descriptor was not open()ed O_RDWR.
EBUSY     o             Someone else has an O_EXCL lock on this device.
EBUSY     w             With mmap-ed IO, the reserved buffer already in use.
EBUSY     <some ioctls> Attempt to change something (e.g. reserved buffer
                        size) when the resource was in use.
EDOM      w,SG_IO       Too many requests queued against this file
                        descriptor. Limit is SG_MAX_QUEUE active requests.
                        If sg_header interface is being used then the
                        default queue depth is 1. Use SG_SET_COMMAND_Q
                        ioctl() to increase it.
EFAULT    w,r,SG_IO     Pointer to user space invalid.
          <most ioctls> 
EINVAL    w,r           Size given as 3rd argument not large enough for the
                        sg_io_hdr_t structure. Both direct and mmap-ed IO
			selected.
EIO       w             Size given as 3rd argument less than size of old
                        header structure (sg_header). Additionally a write()
                        with the old header will yield this error for most
                        detected malformed requests.
EIO       r             A read() with the older sg_header structure yields
			this value for some errors that it detects.
EINTR     o             While waiting for the O_EXCL lock to clear this call
                        was interrupted by a signal.
EINTR     r,SG_IO       While waiting for the request to finish this call
                        was interrupted by a signal.
EINTR     w             [Very unlikely] While waiting for an internal SCSI
                        resource this call was interrupted by a signal.
EMSGSIZE  w,SG_IO       SCSI command size ('cmd_len') was too small 
                        (i.e. < 6) or too large
ENODEV    o             Tried to open() a file with no associated device.
                        [Perhaps sg has not been built into the kernel or
                        is not available as a module?]
ENODEV    o,w,r,SG_IO   SCSI device has detached, awaiting cleanup.
                        User should close fd. Poll() will yield POLLHUP.
ENOENT    o             Given filename not found.
ENOMEM    o             [Very unlikely] Kernel was not even able to find
                        enough memory for this file descriptor's context.
ENOMEM    w,SG_IO       Kernel unable to find memory for internal buffers.
                        This is usually associated with indirect IO.
			For mmap-ed IO 'dxfer_len' greater than reserved
			buffer size.
			Lower level (adapter) driver does not support enough
			scatter gather elements for requested data transfer.
ENOSYS    w,SG_IO       'interface_id' of a sg_io_hdr_t object was _not_ 'S'.
ENXIO     o             "remove-single-device" may have removed this device.
ENXIO     o, w,r,SG_IO  Internal error (including SCSI sub-system busy doing
                        error processing - e.g. SCSI bus reset). When a
			SCSI device is offline, this is the response. This 
			can be bypassed by opening O_NONBLOCK.
EPERM     o             Can't use O_EXCL when open()ing with O_RDONLY
EPERM     w,SG_IO       File descriptor open()-ed O_RDONLY but O_RDWR
          <some ioctls> access mode needed for this operation.