Report the details of the SG_IO ioctl failure if an Error pointer is provided. This information aids troubleshooting and will be used by the SCSI Persistent Reservations migration code.
Signed-off-by: Stefan Hajnoczi <[email protected]> --- include/hw/scsi/scsi.h | 2 +- hw/scsi/scsi-disk.c | 2 +- hw/scsi/scsi-generic.c | 33 ++++++++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 670c477e38..89b1ed6258 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -237,7 +237,7 @@ void scsi_device_unit_attention_reported(SCSIDevice *dev); void scsi_generic_read_device_inquiry(SCSIDevice *dev); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, uint8_t cmd_size, - uint8_t *buf, uint8_t buf_size, uint32_t timeout); + uint8_t *buf, uint8_t buf_size, uint32_t timeout, Error **errp); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun); SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 97ae535a27..76fe5f085b 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2749,7 +2749,7 @@ static int get_device_type(SCSIDiskState *s) cmd[4] = sizeof(buf); ret = scsi_SG_IO(s->qdev.conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), s->qdev.io_timeout); + buf, sizeof(buf), s->qdev.io_timeout, NULL); if (ret < 0) { return -1; } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 61511cf945..2af8803644 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -527,10 +527,10 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_wwn) int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, uint8_t cmd_size, uint8_t *buf, uint8_t buf_size, - uint32_t timeout) + uint32_t timeout, Error **errp) { sg_io_hdr_t io_header; - uint8_t sensebuf[8]; + uint8_t sensebuf[8] = {}; int ret; memset(&io_header, 0, sizeof(io_header)); @@ -550,6 +550,29 @@ int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, io_header.driver_status || io_header.host_status) { trace_scsi_generic_ioctl_sgio_done(cmd[0], ret, io_header.status, io_header.host_status); + if (ret < 0) { + error_setg_errno(errp, -ret, "SG_IO ioctl failed"); + } else { + g_autofree char *sensebuf_hex = + g_strdup_printf("%02x%02x%02x%02x%02x%02x%02x%02x", + sensebuf[0], + sensebuf[1], + sensebuf[2], + sensebuf[3], + sensebuf[4], + sensebuf[5], + sensebuf[6], + sensebuf[7]); + + error_setg(errp, "SG_IO SCSI command failed with status=0x%x " + "driver_status=0x%x host_status=0x%x sensebuf=%s " + "sb_len_wr=%u", + io_header.status, + io_header.driver_status, + io_header.host_status, + sensebuf_hex, + io_header.sb_len_wr); + } return -1; } return 0; @@ -576,7 +599,7 @@ static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s) cmd[4] = sizeof(buf); ret = scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), s->io_timeout); + buf, sizeof(buf), s->io_timeout, NULL); if (ret < 0) { /* * Do not assume anything if we can't retrieve the @@ -612,7 +635,7 @@ static void scsi_generic_read_device_identification(SCSIDevice *s) cmd[4] = sizeof(buf); ret = scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), s->io_timeout); + buf, sizeof(buf), s->io_timeout, NULL); if (ret < 0) { return; } @@ -664,7 +687,7 @@ static int get_stream_blocksize(BlockBackend *blk) cmd[4] = sizeof(buf); ret = scsi_SG_IO(blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), 6); + buf, sizeof(buf), 6, NULL); if (ret < 0) { return -1; } -- 2.52.0
