From 84621d8aa40cb29508b5730c46666c645851bbfd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Dec 2018 12:30:57 +0000 Subject: [PATCH 2/8] hw/scsi: centralize SG_IO calls into single function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Paolo Bonzini Message-id: <20181220123103.29579-3-pbonzini@redhat.com> Patchwork-id: 83711 O-Subject: [PATCH 2/8] hw/scsi: centralize SG_IO calls into single function Bugzilla: 1639957 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Philippe Mathieu-Daudé RH-Acked-by: Kevin Wolf RH-Acked-by: Laurent Vivier From: Daniel Henrique Barboza For the VPD Block Limits emulation with SCSI passthrough, we'll issue an Inquiry request with EVPD set to retrieve the available VPD pages of the device. This would be done in a way similar of what scsi_generic_read_device_identification does: create a SCSI command and a reply buffer, fill in the sg_io_hdr_t structure, call blk_ioctl, check if an error occurred, process the response. This same process is done in other 2 functions, get_device_type and get_stream_blocksize. They differ in the command/reply buffer and post-processing, everything else is almost a copy/paste. Instead of adding a forth copy/pasted-ish code when adding the passthrough VPD BL emulation, this patch extirpates this repetition of those 3 functions and put it into a new one called scsi_SG_IO_FROM_DEV. Any future code that wants to execute an SG_DXFER_FROM_DEV to the device can use it, avoiding filling sg_io_hdr_t again and et cetera. Signed-off-by: Daniel Henrique Barboza Message-Id: <20180627172432.11120-3-danielhb413@gmail.com> Signed-off-by: Paolo Bonzini (cherry picked from commit a0c7e35b17b3d2cade8a5fc8e57904e02fb91fe4) Signed-off-by: Danilo C. L. de Paula --- hw/scsi/scsi-disk.c | 18 +++------------ hw/scsi/scsi-generic.c | 61 +++++++++++++++++++++++++------------------------- include/hw/scsi/scsi.h | 2 ++ 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index ae5b4c0..ea86849 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2579,8 +2579,6 @@ static int get_device_type(SCSIDiskState *s) { uint8_t cmd[16]; uint8_t buf[36]; - uint8_t sensebuf[8]; - sg_io_hdr_t io_header; int ret; memset(cmd, 0, sizeof(cmd)); @@ -2588,19 +2586,9 @@ static int get_device_type(SCSIDiskState *s) cmd[0] = INQUIRY; cmd[4] = sizeof(buf); - memset(&io_header, 0, sizeof(io_header)); - io_header.interface_id = 'S'; - io_header.dxfer_direction = SG_DXFER_FROM_DEV; - io_header.dxfer_len = sizeof(buf); - io_header.dxferp = buf; - io_header.cmdp = cmd; - io_header.cmd_len = sizeof(cmd); - io_header.mx_sb_len = sizeof(sensebuf); - io_header.sbp = sensebuf; - io_header.timeout = 6000; /* XXX */ - - ret = blk_ioctl(s->qdev.conf.blk, SG_IO, &io_header); - if (ret < 0 || io_header.driver_status || io_header.host_status) { + ret = scsi_SG_IO_FROM_DEV(s->qdev.conf.blk, cmd, sizeof(cmd), + buf, sizeof(buf)); + if (ret < 0) { return -1; } s->qdev.type = buf[0]; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 796162c..c6307a8 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -410,35 +410,48 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_wwn) return -EINVAL; } -void scsi_generic_read_device_identification(SCSIDevice *s) +int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, + uint8_t *buf, uint8_t buf_size) { - uint8_t cmd[6]; - uint8_t buf[250]; - uint8_t sensebuf[8]; sg_io_hdr_t io_header; + uint8_t sensebuf[8]; int ret; - int i, len; - - memset(cmd, 0, sizeof(cmd)); - memset(buf, 0, sizeof(buf)); - cmd[0] = INQUIRY; - cmd[1] = 1; - cmd[2] = 0x83; - cmd[4] = sizeof(buf); memset(&io_header, 0, sizeof(io_header)); io_header.interface_id = 'S'; io_header.dxfer_direction = SG_DXFER_FROM_DEV; - io_header.dxfer_len = sizeof(buf); + io_header.dxfer_len = buf_size; io_header.dxferp = buf; io_header.cmdp = cmd; - io_header.cmd_len = sizeof(cmd); + io_header.cmd_len = cmd_size; io_header.mx_sb_len = sizeof(sensebuf); io_header.sbp = sensebuf; io_header.timeout = 6000; /* XXX */ - ret = blk_ioctl(s->conf.blk, SG_IO, &io_header); + ret = blk_ioctl(blk, SG_IO, &io_header); if (ret < 0 || io_header.driver_status || io_header.host_status) { + return -1; + } + return 0; +} + +void scsi_generic_read_device_identification(SCSIDevice *s) +{ + uint8_t cmd[6]; + uint8_t buf[250]; + int ret; + int i, len; + + memset(cmd, 0, sizeof(cmd)); + memset(buf, 0, sizeof(buf)); + cmd[0] = INQUIRY; + cmd[1] = 1; + cmd[2] = 0x83; + cmd[4] = sizeof(buf); + + ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd), + buf, sizeof(buf)); + if (ret < 0) { return; } @@ -471,8 +484,6 @@ static int get_stream_blocksize(BlockBackend *blk) { uint8_t cmd[6]; uint8_t buf[12]; - uint8_t sensebuf[8]; - sg_io_hdr_t io_header; int ret; memset(cmd, 0, sizeof(cmd)); @@ -480,21 +491,11 @@ static int get_stream_blocksize(BlockBackend *blk) cmd[0] = MODE_SENSE; cmd[4] = sizeof(buf); - memset(&io_header, 0, sizeof(io_header)); - io_header.interface_id = 'S'; - io_header.dxfer_direction = SG_DXFER_FROM_DEV; - io_header.dxfer_len = sizeof(buf); - io_header.dxferp = buf; - io_header.cmdp = cmd; - io_header.cmd_len = sizeof(cmd); - io_header.mx_sb_len = sizeof(sensebuf); - io_header.sbp = sensebuf; - io_header.timeout = 6000; /* XXX */ - - ret = blk_ioctl(blk, SG_IO, &io_header); - if (ret < 0 || io_header.driver_status || io_header.host_status) { + ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf)); + if (ret < 0) { return -1; } + return (buf[9] << 16) | (buf[10] << 8) | buf[11]; } diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 5930a43..b6e05c4 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -189,6 +189,8 @@ void scsi_device_unit_attention_reported(SCSIDevice *dev); void scsi_generic_read_device_identification(SCSIDevice *dev); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf); +int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, + uint8_t *buf, uint8_t buf_size); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun); /* scsi-generic.c. */ -- 1.8.3.1