* [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation
@ 2009-01-28 14:51 Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 1/3] fix signed/unsigned overflows in SCSI disk Rik van Riel
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Rik van Riel @ 2009-01-28 14:51 UTC (permalink / raw)
To: qemu-devel
This small patch series contains several fixes for the
SCSI disk emulation:
- fixes for signed/unsigned overflows
- support for >2TB SCSI disks
- report the correct number of sectors in read capacity
Thanks go out to Paul Brook and Jamie Lokier for reviewing
earlier versions of these patches and pointing additional
TODOs.
--
All rights reversed.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 1/3] fix signed/unsigned overflows in SCSI disk
2009-01-28 14:51 [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Rik van Riel
@ 2009-01-28 14:51 ` Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 2/3] support >2TB SCSI disks Rik van Riel
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Rik van Riel @ 2009-01-28 14:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: qemu-upstream.diff --]
[-- Type: text/plain, Size: 1784 bytes --]
Sector numbers can overflow on a virtual scsi disk of over 1TB
in size. Qemu's bdrv_read expects an int64_t, so fix the overflow
by going to that data type.
On large disks, we clip the capacity to 2TB instead of returning
"capacity modulo 2TB".
Turn sector_count into an unsigned to prevent a signed/unsigned
overflow with SCSI transfers larger than 2TB. We're unlikely to
ever hit this bug, but fixing it is just one line.
Signed-off-by: Rik van Riel <riel@redhat.com>
Index: qemu/trunk/hw/scsi-disk.c
===================================================================
--- qemu.orig/trunk/hw/scsi-disk.c
+++ qemu/trunk/hw/scsi-disk.c
@@ -47,11 +47,11 @@ do { fprintf(stderr, "scsi-disk: " fmt ,
typedef struct SCSIRequest {
SCSIDeviceState *dev;
uint32_t tag;
- /* ??? We should probably keep track of whether the data trasfer is
+ /* ??? We should probably keep track of whether the data transfer is
a read or a write. Currently we rely on the host getting it right. */
/* Both sector and sector_count are in terms of qemu 512 byte blocks. */
- int sector;
- int sector_count;
+ uint64_t sector;
+ uint32_t sector_count;
/* The amounnt of data in the buffer. */
int buf_len;
uint8_t *dma_buf;
@@ -731,6 +731,9 @@ static int32_t scsi_send_command(SCSIDev
/* Returned value is the address of the last sector. */
if (nb_sectors) {
nb_sectors--;
+ /* Clip to 2TB, instead of returning capacity modulo 2TB. */
+ if (nb_sectors > UINT32_MAX)
+ nb_sectors = UINT32_MAX;
outbuf[0] = (nb_sectors >> 24) & 0xff;
outbuf[1] = (nb_sectors >> 16) & 0xff;
outbuf[2] = (nb_sectors >> 8) & 0xff;
--
All rights reversed.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 2/3] support >2TB SCSI disks
2009-01-28 14:51 [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 1/3] fix signed/unsigned overflows in SCSI disk Rik van Riel
@ 2009-01-28 14:51 ` Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size Rik van Riel
2009-01-28 21:59 ` [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Anthony Liguori
3 siblings, 0 replies; 8+ messages in thread
From: Rik van Riel @ 2009-01-28 14:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: qemu-scsi-largedisks.patch --]
[-- Type: text/plain, Size: 4543 bytes --]
Implement SCSI READ(16), WRITE(16) and SAI READ CAPACITY(16) commands,
so SCSI disks larger than 2TB can work with guests that support these
newer SCSI commands.
The cast to (uint64_t) is needed because otherwise gcc will use a
signed int, which gets sign extended into uint64_t lba, resulting
in bad block numbers for READ 10 and READ 16 with block numbers
larger than 2^31.
Signed-off-by: Rik van Riel <riel@redhat.com>
Index: qemu/trunk/hw/scsi-disk.c
===================================================================
--- qemu.orig/trunk/hw/scsi-disk.c
+++ qemu/trunk/hw/scsi-disk.c
@@ -346,7 +346,7 @@ static int32_t scsi_send_command(SCSIDev
{
SCSIDeviceState *s = d->state;
uint64_t nb_sectors;
- uint32_t lba;
+ uint64_t lba;
uint32_t len;
int cmdlen;
int is_write;
@@ -368,23 +368,29 @@ static int32_t scsi_send_command(SCSIDev
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
switch (command >> 5) {
case 0:
- lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
+ lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
+ (((uint64_t) buf[1] & 0x1f) << 16);
len = buf[4];
cmdlen = 6;
break;
case 1:
case 2:
- lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
+ lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
+ ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[8] | (buf[7] << 8);
cmdlen = 10;
break;
case 4:
- lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
+ lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
+ ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
+ ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
+ ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
cmdlen = 16;
break;
case 5:
- lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
+ lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
+ ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
cmdlen = 12;
break;
@@ -750,13 +756,15 @@ static int32_t scsi_send_command(SCSIDev
break;
case 0x08:
case 0x28:
- DPRINTF("Read (sector %d, count %d)\n", lba, len);
+ case 0x88:
+ DPRINTF("Read (sector %lld, count %d)\n", lba, len);
r->sector = lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
break;
case 0x0a:
case 0x2a:
- DPRINTF("Write (sector %d, count %d)\n", lba, len);
+ case 0x8a:
+ DPRINTF("Write (sector %lld, count %d)\n", lba, len);
r->sector = lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
is_write = 1;
@@ -820,6 +828,37 @@ static int32_t scsi_send_command(SCSIDev
if (buf[1] & 3)
goto fail;
break;
+ case 0x9e:
+ /* Service Action In subcommands. */
+ if ((buf[1] & 31) == 0x10) {
+ DPRINTF("SAI READ CAPACITY(16)\n");
+ memset(outbuf, 0, len);
+ bdrv_get_geometry(s->bdrv, &nb_sectors);
+ /* Returned value is the address of the last sector. */
+ if (nb_sectors) {
+ nb_sectors--;
+ outbuf[0] = (nb_sectors >> 56) & 0xff;
+ outbuf[1] = (nb_sectors >> 48) & 0xff;
+ outbuf[2] = (nb_sectors >> 40) & 0xff;
+ outbuf[3] = (nb_sectors >> 32) & 0xff;
+ outbuf[4] = (nb_sectors >> 24) & 0xff;
+ outbuf[5] = (nb_sectors >> 16) & 0xff;
+ outbuf[6] = (nb_sectors >> 8) & 0xff;
+ outbuf[7] = nb_sectors & 0xff;
+ outbuf[8] = 0;
+ outbuf[9] = 0;
+ outbuf[10] = s->cluster_size * 2;
+ outbuf[11] = 0;
+ /* Protection, exponent and lowest lba field left blank. */
+ r->buf_len = len;
+ } else {
+ scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
+ return 0;
+ }
+ break;
+ }
+ DPRINTF("Unsupported Service Action In\n");
+ goto fail;
case 0xa0:
DPRINTF("Report LUNs (len %d)\n", len);
if (len < 16)
--
All rights reversed.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size
2009-01-28 14:51 [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 1/3] fix signed/unsigned overflows in SCSI disk Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 2/3] support >2TB SCSI disks Rik van Riel
@ 2009-01-28 14:51 ` Rik van Riel
2009-01-28 16:49 ` Rene Rebe
2009-01-28 21:42 ` Anthony Liguori
2009-01-28 21:59 ` [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Anthony Liguori
3 siblings, 2 replies; 8+ messages in thread
From: Rik van Riel @ 2009-01-28 14:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: qemu-capacity-sectors.patch --]
[-- Type: text/plain, Size: 1316 bytes --]
Paul Brook pointed out that the number of sectors reported
by the SCSI read capacity commands needs to be divided by
s->cluster_size, because bdrv_get_geometry reports the number
of 512 byte sectors, while emulated CDROMs report 2048 byte
sectors back to the guest.
This has no consequences for emulated hard disks, which use
a cluster size of 1.
Signed-off-by: Rik van Riel <riel@redhat.com>
Index: qemu/trunk/hw/scsi-disk.c
===================================================================
--- qemu.orig/trunk/hw/scsi-disk.c
+++ qemu/trunk/hw/scsi-disk.c
@@ -734,6 +734,7 @@ static int32_t scsi_send_command(SCSIDev
/* The normal LEN field for this command is zero. */
memset(outbuf, 0, 8);
bdrv_get_geometry(s->bdrv, &nb_sectors);
+ nb_sectors =/ s->cluster_size;
/* Returned value is the address of the last sector. */
if (nb_sectors) {
nb_sectors--;
@@ -834,6 +835,7 @@ static int32_t scsi_send_command(SCSIDev
DPRINTF("SAI READ CAPACITY(16)\n");
memset(outbuf, 0, len);
bdrv_get_geometry(s->bdrv, &nb_sectors);
+ nb_sectors =/ s->cluster_size;
/* Returned value is the address of the last sector. */
if (nb_sectors) {
nb_sectors--;
--
All rights reversed.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size
2009-01-28 14:51 ` [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size Rik van Riel
@ 2009-01-28 16:49 ` Rene Rebe
2009-01-28 16:52 ` Rik van Riel
2009-01-28 21:42 ` Anthony Liguori
1 sibling, 1 reply; 8+ messages in thread
From: Rene Rebe @ 2009-01-28 16:49 UTC (permalink / raw)
To: qemu-devel
Hi,
> --- qemu.orig/trunk/hw/scsi-disk.c
> +++ qemu/trunk/hw/scsi-disk.c
> @@ -734,6 +734,7 @@ static int32_t scsi_send_command(SCSIDev
> /* The normal LEN field for this command is zero. */
> memset(outbuf, 0, 8);
> bdrv_get_geometry(s->bdrv, &nb_sectors);
> + nb_sectors =/ s->cluster_size;
/=
> /* Returned value is the address of the last sector. */
> if (nb_sectors) {
> nb_sectors--;
> @@ -834,6 +835,7 @@ static int32_t scsi_send_command(SCSIDev
> DPRINTF("SAI READ CAPACITY(16)\n");
> memset(outbuf, 0, len);
> bdrv_get_geometry(s->bdrv, &nb_sectors);
> + nb_sectors =/ s->cluster_size;
dito?
> /* Returned value is the address of the last sector. */
> if (nb_sectors) {
> nb_sectors--;
--
René Rebe - ExactCODE GmbH - Europe, Germany, Berlin
http://exactcode.de | http://t2-project.org | http://rene.rebe.name
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size
2009-01-28 16:49 ` Rene Rebe
@ 2009-01-28 16:52 ` Rik van Riel
0 siblings, 0 replies; 8+ messages in thread
From: Rik van Riel @ 2009-01-28 16:52 UTC (permalink / raw)
To: Rene Rebe; +Cc: qemu-devel
Rene Rebe wrote:
> Hi,
>
> > --- qemu.orig/trunk/hw/scsi-disk.c
> > +++ qemu/trunk/hw/scsi-disk.c
> > @@ -734,6 +734,7 @@ static int32_t scsi_send_command(SCSIDev
> > /* The normal LEN field for this command is zero. */
> > memset(outbuf, 0, 8);
> > bdrv_get_geometry(s->bdrv, &nb_sectors);
> > + nb_sectors =/ s->cluster_size;
>
> /=
Doh! That's what I get for trying to make the code a little
nicer after compiling it.
--
All rights reversed.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size
2009-01-28 14:51 ` [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size Rik van Riel
2009-01-28 16:49 ` Rene Rebe
@ 2009-01-28 21:42 ` Anthony Liguori
1 sibling, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2009-01-28 21:42 UTC (permalink / raw)
To: qemu-devel
Rik van Riel wrote:
> ndex: qemu/trunk/hw/scsi-disk.c
> ===================================================================
> --- qemu.orig/trunk/hw/scsi-disk.c
> +++ qemu/trunk/hw/scsi-disk.c
> @@ -734,6 +734,7 @@ static int32_t scsi_send_command(SCSIDev
> /* The normal LEN field for this command is zero. */
> memset(outbuf, 0, 8);
> bdrv_get_geometry(s->bdrv, &nb_sectors);
> + nb_sectors =/ s->cluster_size;
An emoticon, perhaps, but certainly not a C operator.. :-)
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation
2009-01-28 14:51 [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Rik van Riel
` (2 preceding siblings ...)
2009-01-28 14:51 ` [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size Rik van Riel
@ 2009-01-28 21:59 ` Anthony Liguori
3 siblings, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2009-01-28 21:59 UTC (permalink / raw)
To: qemu-devel
Rik van Riel wrote:
> This small patch series contains several fixes for the
> SCSI disk emulation:
> - fixes for signed/unsigned overflows
> - support for >2TB SCSI disks
> - report the correct number of sectors in read capacity
>
> Thanks go out to Paul Brook and Jamie Lokier for reviewing
> earlier versions of these patches and pointing additional
> TODOs.
>
>
Applied (fixing patch 3). Thanks.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-01-28 22:00 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-28 14:51 [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 1/3] fix signed/unsigned overflows in SCSI disk Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 2/3] support >2TB SCSI disks Rik van Riel
2009-01-28 14:51 ` [Qemu-devel] [PATCH 3/3] SCSI divide capacity by s->cluster_size Rik van Riel
2009-01-28 16:49 ` Rene Rebe
2009-01-28 16:52 ` Rik van Riel
2009-01-28 21:42 ` Anthony Liguori
2009-01-28 21:59 ` [Qemu-devel] [PATCH 0/3] fixes for the SCSI disk emulation Anthony Liguori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).