From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:41143) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKruf-0005ED-F8 for qemu-devel@nongnu.org; Mon, 31 Oct 2011 09:28:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RKrue-0004Qt-2F for qemu-devel@nongnu.org; Mon, 31 Oct 2011 09:28:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:7061) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKrud-0004Qe-Qi for qemu-devel@nongnu.org; Mon, 31 Oct 2011 09:28:28 -0400 From: Kevin Wolf Date: Mon, 31 Oct 2011 14:30:18 +0100 Message-Id: <1320067830-12093-44-git-send-email-kwolf@redhat.com> In-Reply-To: <1320067830-12093-1-git-send-email-kwolf@redhat.com> References: <1320067830-12093-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 43/55] scsi-generic: snoop READ CAPACITY commands to get block size List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: anthony@codemonkey.ws Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Paolo Bonzini Instead of "guessing" the block size when there is no medium in the drive, wait for the guest to send a READ CAPACITY command and snoop it from there. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/scsi-generic.c | 66 ++++++++++++++++++++--------------------------------- 1 files changed, 25 insertions(+), 41 deletions(-) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 5ad3d57..4d7ad82 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -155,6 +155,7 @@ static int execute_command(BlockDriverState *bdrv, static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; + SCSIDevice *s = r->req.dev; int len; r->req.aiocb = NULL; @@ -170,6 +171,15 @@ static void scsi_read_complete(void * opaque, int ret) if (len == 0) { scsi_command_complete(r, 0); } else { + /* Snoop READ CAPACITY output to set the blocksize. */ + if (r->req.cmd.buf[0] == READ_CAPACITY_10) { + s->blocksize = ldl_be_p(&r->buf[4]); + } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && + (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { + s->blocksize = ldl_be_p(&r->buf[8]); + } + bdrv_set_buffer_alignment(s->conf.bs, s->blocksize); + scsi_req_data(&r->req, len); } } @@ -298,36 +308,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) } } -static int get_blocksize(BlockDriverState *bdrv) -{ - uint8_t cmd[10]; - uint8_t buf[8]; - uint8_t sensebuf[8]; - sg_io_hdr_t io_header; - int ret; - - memset(cmd, 0, sizeof(cmd)); - memset(buf, 0, sizeof(buf)); - cmd[0] = READ_CAPACITY_10; - - 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 = bdrv_ioctl(bdrv, SG_IO, &io_header); - if (ret < 0 || io_header.driver_status || io_header.host_status) { - return -1; - } - return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; -} - static int get_stream_blocksize(BlockDriverState *bdrv) { uint8_t cmd[6]; @@ -413,21 +393,25 @@ static int scsi_generic_initfn(SCSIDevice *s) /* define device state */ s->type = scsiid.scsi_type; DPRINTF("device type %d\n", s->type); - if (s->type == TYPE_TAPE) { + switch (s->type) { + case TYPE_TAPE: s->blocksize = get_stream_blocksize(s->conf.bs); if (s->blocksize == -1) { s->blocksize = 0; } - } else { - s->blocksize = get_blocksize(s->conf.bs); - /* removable media returns 0 if not present */ - if (s->blocksize <= 0) { - if (s->type == TYPE_ROM || s->type == TYPE_WORM) { - s->blocksize = 2048; - } else { - s->blocksize = 512; - } - } + break; + + /* Make a guess for block devices, we'll fix it when the guest sends. + * READ CAPACITY. If they don't, they likely would assume these sizes + * anyway. (TODO: they could also send MODE SENSE). + */ + case TYPE_ROM: + case TYPE_WORM: + s->blocksize = 2048; + break; + default: + s->blocksize = 512; + break; } DPRINTF("block size %d\n", s->blocksize); -- 1.7.6.4