* [Qemu-devel] [PATCH v2 1/3] hw/scsi: Fix debug message of cdb structure in scsi-generic
2017-01-19 20:51 [Qemu-devel] [PATCH v2 0/3] scsi-generic and BLKSECTGET Eric Farman
@ 2017-01-19 20:51 ` Eric Farman
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 2/3] block: Fix target variable of BLKSECTGET ioctl Eric Farman
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices Eric Farman
2 siblings, 0 replies; 7+ messages in thread
From: Eric Farman @ 2017-01-19 20:51 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Eric Farman, pbonzini
When running with debug enabled, the scsi-generic cdb that is
dumped skips byte 0 of the command, which is the opcode. This
makes identifying which command is being issued/completed a
little difficult. Example:
0x00 0x00 0x01 0x00 0x00
scsi-generic: scsi_read_data 0x0
scsi-generic: Data ready tag=0x0 len=164
scsi-generic: scsi_read_data 0x0
scsi-generic: Command complete 0x0x10a42c60 tag=0x0 status=0
Improve this by adding a message prior to the loop, similar to
what exists for scsi-disk. Clean up a few other messages to be
more explicit of what is being represented. Example:
scsi-generic: Command: data=0x12 0x00 0x00 0x01 0x00 0x00
scsi-generic: scsi_read_data tag=0x0
scsi-generic: Data ready tag=0x0 len=164
scsi-generic: scsi_read_data tag=0x0
scsi-generic: Command complete 0x0x10a452d0 tag=0x0 status=0
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
---
hw/scsi/scsi-generic.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 7a588a7..92f091a 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -246,7 +246,7 @@ static void scsi_read_data(SCSIRequest *req)
SCSIDevice *s = r->req.dev;
int ret;
- DPRINTF("scsi_read_data 0x%x\n", req->tag);
+ DPRINTF("scsi_read_data tag=0x%x\n", req->tag);
/* The request is used as the AIO opaque value, so add a ref. */
scsi_req_ref(&r->req);
@@ -294,7 +294,7 @@ static void scsi_write_data(SCSIRequest *req)
SCSIDevice *s = r->req.dev;
int ret;
- DPRINTF("scsi_write_data 0x%x\n", req->tag);
+ DPRINTF("scsi_write_data tag=0x%x\n", req->tag);
if (r->len == 0) {
r->len = r->buflen;
scsi_req_data(&r->req, r->len);
@@ -329,6 +329,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
int ret;
#ifdef DEBUG_SCSI
+ DPRINTF("Command: data=0x%02x", cmd[0]);
{
int i;
for (i = 1; i < r->req.cmd.len; i++) {
--
2.8.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 2/3] block: Fix target variable of BLKSECTGET ioctl
2017-01-19 20:51 [Qemu-devel] [PATCH v2 0/3] scsi-generic and BLKSECTGET Eric Farman
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 1/3] hw/scsi: Fix debug message of cdb structure in scsi-generic Eric Farman
@ 2017-01-19 20:51 ` Eric Farman
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices Eric Farman
2 siblings, 0 replies; 7+ messages in thread
From: Eric Farman @ 2017-01-19 20:51 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Eric Farman, kwolf, mreitz
Commit 6f607174 introduced a routine to call the kernel BLKSECTGET
ioctl, which stores the result back to user space. However, the
size of the data returned depends on the routine handling the ioctl.
The (compat_)blkdev_ioctl returns a short, while sg_ioctl returns
an int. Thus, on big-endian systems, we can find ourselves
accidentally shifting the result to a much larger value.
(On s390x, a short is 16 bits while an int is 32 bits.)
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
---
block/file-posix.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index 28b47d9..2115155 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -651,12 +651,15 @@ static void raw_reopen_abort(BDRVReopenState *state)
state->opaque = NULL;
}
-static int hdev_get_max_transfer_length(int fd)
+static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
{
#ifdef BLKSECTGET
int max_sectors = 0;
- if (ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
+ short max_sectors_short = 0;
+ if (bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
return max_sectors;
+ } else if (!bs->sg && ioctl(fd, BLKSECTGET, &max_sectors_short) == 0) {
+ return max_sectors_short;
} else {
return -errno;
}
@@ -672,7 +675,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
if (!fstat(s->fd, &st)) {
if (S_ISBLK(st.st_mode)) {
- int ret = hdev_get_max_transfer_length(s->fd);
+ int ret = hdev_get_max_transfer_length(bs, s->fd);
if (ret > 0 && ret <= BDRV_REQUEST_MAX_SECTORS) {
bs->bl.max_transfer = pow2floor(ret << BDRV_SECTOR_BITS);
}
--
2.8.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices
2017-01-19 20:51 [Qemu-devel] [PATCH v2 0/3] scsi-generic and BLKSECTGET Eric Farman
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 1/3] hw/scsi: Fix debug message of cdb structure in scsi-generic Eric Farman
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 2/3] block: Fix target variable of BLKSECTGET ioctl Eric Farman
@ 2017-01-19 20:51 ` Eric Farman
2017-01-20 9:31 ` Fam Zheng
2 siblings, 1 reply; 7+ messages in thread
From: Eric Farman @ 2017-01-19 20:51 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Eric Farman, kwolf, mreitz
Commit 6f607174 introduced a routine to get the maximum number
of bytes for a single I/O transfer for block devices, however
scsi generic devices are character devices, not block. Add
a condition for this, such that scsi generic devices can view
the same data.
Some tweaking of data is required, because the block and sg
ioctls return values in different scales (sectors versus
bytes). So adjust hdev_get_max_transfer_length such that it
always returns a value in bytes.
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
---
block/file-posix.c | 10 ++++++----
include/block/block.h | 1 +
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index 2115155..94068ca 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -657,9 +657,11 @@ static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
int max_sectors = 0;
short max_sectors_short = 0;
if (bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
+ /* sg returns a value in bytes */
return max_sectors;
} else if (!bs->sg && ioctl(fd, BLKSECTGET, &max_sectors_short) == 0) {
- return max_sectors_short;
+ /* block returns a value in sectors */
+ return max_sectors_short << BDRV_SECTOR_BITS;
} else {
return -errno;
}
@@ -674,10 +676,10 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
struct stat st;
if (!fstat(s->fd, &st)) {
- if (S_ISBLK(st.st_mode)) {
+ if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
int ret = hdev_get_max_transfer_length(bs, s->fd);
- if (ret > 0 && ret <= BDRV_REQUEST_MAX_SECTORS) {
- bs->bl.max_transfer = pow2floor(ret << BDRV_SECTOR_BITS);
+ if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
+ bs->bl.max_transfer = pow2floor(ret);
}
}
}
diff --git a/include/block/block.h b/include/block/block.h
index 8b0dcda..4e81f20 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -116,6 +116,7 @@ typedef struct HDGeometry {
#define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \
INT_MAX >> BDRV_SECTOR_BITS)
+#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
/*
* Allocation status flags
--
2.8.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices
2017-01-19 20:51 ` [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices Eric Farman
@ 2017-01-20 9:31 ` Fam Zheng
2017-01-20 9:53 ` Fam Zheng
0 siblings, 1 reply; 7+ messages in thread
From: Fam Zheng @ 2017-01-20 9:31 UTC (permalink / raw)
To: Eric Farman; +Cc: qemu-devel, qemu-block, kwolf, mreitz
On Thu, 01/19 21:51, Eric Farman wrote:
> Commit 6f607174 introduced a routine to get the maximum number
> of bytes for a single I/O transfer for block devices, however
> scsi generic devices are character devices, not block. Add
> a condition for this, such that scsi generic devices can view
> the same data.
>
> Some tweaking of data is required, because the block and sg
> ioctls return values in different scales (sectors versus
> bytes). So adjust hdev_get_max_transfer_length such that it
> always returns a value in bytes.
>
> Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
> ---
> block/file-posix.c | 10 ++++++----
> include/block/block.h | 1 +
> 2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/block/file-posix.c b/block/file-posix.c
> index 2115155..94068ca 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -657,9 +657,11 @@ static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
> int max_sectors = 0;
> short max_sectors_short = 0;
> if (bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
> + /* sg returns a value in bytes */
> return max_sectors;
The variable name is now misleading, maybe use "bytes" instead?
> } else if (!bs->sg && ioctl(fd, BLKSECTGET, &max_sectors_short) == 0) {
> - return max_sectors_short;
> + /* block returns a value in sectors */
> + return max_sectors_short << BDRV_SECTOR_BITS;
> } else {
> return -errno;
> }
> @@ -674,10 +676,10 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
> struct stat st;
>
> if (!fstat(s->fd, &st)) {
> - if (S_ISBLK(st.st_mode)) {
> + if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
> int ret = hdev_get_max_transfer_length(bs, s->fd);
> - if (ret > 0 && ret <= BDRV_REQUEST_MAX_SECTORS) {
> - bs->bl.max_transfer = pow2floor(ret << BDRV_SECTOR_BITS);
> + if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
> + bs->bl.max_transfer = pow2floor(ret);
> }
> }
> }
> diff --git a/include/block/block.h b/include/block/block.h
> index 8b0dcda..4e81f20 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -116,6 +116,7 @@ typedef struct HDGeometry {
>
> #define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \
> INT_MAX >> BDRV_SECTOR_BITS)
> +#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
>
> /*
> * Allocation status flags
> --
> 2.8.4
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices
2017-01-20 9:31 ` Fam Zheng
@ 2017-01-20 9:53 ` Fam Zheng
2017-01-20 11:34 ` Eric Farman
0 siblings, 1 reply; 7+ messages in thread
From: Fam Zheng @ 2017-01-20 9:53 UTC (permalink / raw)
To: Eric Farman; +Cc: kwolf, qemu-devel, qemu-block, mreitz
On Fri, 01/20 17:31, Fam Zheng wrote:
> > diff --git a/block/file-posix.c b/block/file-posix.c
> > index 2115155..94068ca 100644
> > --- a/block/file-posix.c
> > +++ b/block/file-posix.c
> > @@ -657,9 +657,11 @@ static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
> > int max_sectors = 0;
> > short max_sectors_short = 0;
> > if (bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
> > + /* sg returns a value in bytes */
> > return max_sectors;
>
> The variable name is now misleading, maybe use "bytes" instead?
BTW patch 2 should already make the function return bytes consistently. Doing
it here is meaningless code churn.
Fam
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 3/3] block: get max_transfer limit for char (scsi-generic) devices
2017-01-20 9:53 ` Fam Zheng
@ 2017-01-20 11:34 ` Eric Farman
0 siblings, 0 replies; 7+ messages in thread
From: Eric Farman @ 2017-01-20 11:34 UTC (permalink / raw)
To: Fam Zheng; +Cc: kwolf, qemu-devel, qemu-block, mreitz
On 01/20/2017 04:53 AM, Fam Zheng wrote:
> On Fri, 01/20 17:31, Fam Zheng wrote:
>>> diff --git a/block/file-posix.c b/block/file-posix.c
>>> index 2115155..94068ca 100644
>>> --- a/block/file-posix.c
>>> +++ b/block/file-posix.c
>>> @@ -657,9 +657,11 @@ static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
>>> int max_sectors = 0;
>>> short max_sectors_short = 0;
>>> if (bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
>>> + /* sg returns a value in bytes */
>>> return max_sectors;
>>
>> The variable name is now misleading, maybe use "bytes" instead?
>
> BTW patch 2 should already make the function return bytes consistently. Doing
> it here is meaningless code churn.
Excellent points. Spinning v3 now.
- Eric
^ permalink raw reply [flat|nested] 7+ messages in thread