* [RFC] [PATCH] SCSI passthrough for virtio-blk
@ 2008-08-29 9:28 Hannes Reinecke
2008-08-29 11:01 ` Christian Borntraeger
0 siblings, 1 reply; 7+ messages in thread
From: Hannes Reinecke @ 2008-08-29 9:28 UTC (permalink / raw)
To: Virtualization; +Cc: kvm
[-- Attachment #1: Type: text/plain, Size: 998 bytes --]
Hi all,
I got bored and implemented SCSI passthrough for the virtio-blk driver.
Principle is quite simple, just put the missing fields (cdb, sense and
status header) on the virtio queue and then call the SG_IO ioctl on the
host.
So when using '-drive file=/dev/sgXX,if=virtio,format=host_device' you
can happily call any sg_XX command on the resulting vdX device. Quite
neat, methinks. And it's even backwards compatible, so each of these
patches should work without the other one applied.
As one would have guessed there are two patches, one for the linux
kernel to modify the virtio-blk driver in the guest and one for the
qemu/kvm userland program to modify the virtio-blk driver on the host.
This patch is relative to avi's kvm-userland tree from kernel.org.
As usual, comments etc to me.
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)
[-- Attachment #2: kvm-kernel-virtio-scsi-passthrough --]
[-- Type: text/plain, Size: 3654 bytes --]
virtio: Implement SCSI passthrough for virtio-blk
This patch implements SCSI passthrough for any virtio-blk device.
The data on the virtio queue will only be modified for a SCSI command,
so the normal I/O flow is unchanged.
Signed-off-by: Hannes Reinecke <hare@suse.de>
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 4225109..46f03d2 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -35,6 +35,7 @@ struct virtblk_req
struct list_head list;
struct request *req;
struct virtio_blk_outhdr out_hdr;
+ struct virtio_blk_inhdr in_hdr;
u8 status;
};
@@ -47,20 +48,29 @@ static void blk_done(struct virtqueue *vq)
spin_lock_irqsave(&vblk->lock, flags);
while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
- int uptodate;
+ int error;
+ unsigned int bytes;
switch (vbr->status) {
case VIRTIO_BLK_S_OK:
- uptodate = 1;
+ error = 0;
break;
case VIRTIO_BLK_S_UNSUPP:
- uptodate = -ENOTTY;
+ error = -ENOTTY;
break;
default:
- uptodate = 0;
+ error = -EIO;
break;
}
- end_dequeued_request(vbr->req, uptodate);
+ if (blk_pc_request(vbr->req)) {
+ vbr->req->data_len = vbr->in_hdr.residual;
+ bytes = vbr->in_hdr.data_len;
+ vbr->req->sense_len = vbr->in_hdr.sense_len;
+ vbr->req->errors = vbr->in_hdr.status;
+ } else
+ bytes = blk_rq_bytes(vbr->req);
+
+ __blk_end_request(vbr->req, error, bytes);
list_del(&vbr->list);
mempool_free(vbr, vblk->pool);
}
@@ -72,7 +82,7 @@ static void blk_done(struct virtqueue *vq)
static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
struct request *req)
{
- unsigned long num, out, in;
+ unsigned long num, out = 0, in = 0;
struct virtblk_req *vbr;
vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
@@ -99,20 +109,31 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
/* This init could be done at vblk creation time */
sg_init_table(vblk->sg, VIRTIO_MAX_SG);
- sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
- num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
- sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status));
-
- if (rq_data_dir(vbr->req) == WRITE) {
- vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
- out = 1 + num;
- in = 1;
- } else {
- vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
- out = 1;
- in = 1 + num;
+ sg_set_buf(&vblk->sg[out], &vbr->out_hdr, sizeof(vbr->out_hdr));
+ out++;
+ if (blk_pc_request(vbr->req)) {
+ sg_set_buf(&vblk->sg[out], vbr->req->cmd, vbr->req->cmd_len);
+ out++;
+ }
+ num = blk_rq_map_sg(q, vbr->req, vblk->sg+out);
+ if (blk_pc_request(vbr->req)) {
+ sg_set_buf(&vblk->sg[num+out+in], vbr->req->sense, 96);
+ in++;
+ sg_set_buf(&vblk->sg[num+out+in], &vbr->in_hdr,
+ sizeof(vbr->in_hdr));
+ in++;
+ }
+ sg_set_buf(&vblk->sg[num+out+in], &vbr->status, sizeof(vbr->status));
+ in++;
+ if (num) {
+ if (rq_data_dir(vbr->req) == WRITE) {
+ vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+ out += num;
+ } else {
+ vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+ in += num;
+ }
}
-
if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) {
mempool_free(vbr, vblk->pool);
return false;
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
index c1aef85..089e596 100644
--- a/include/linux/virtio_blk.h
+++ b/include/linux/virtio_blk.h
@@ -54,6 +54,14 @@ struct virtio_blk_outhdr
__u64 sector;
};
+struct virtio_blk_inhdr
+{
+ __u32 status;
+ __u32 data_len;
+ __u32 sense_len;
+ __u32 residual;
+};
+
/* And this is the final byte of the write scatter-gather list. */
#define VIRTIO_BLK_S_OK 0
#define VIRTIO_BLK_S_IOERR 1
[-- Attachment #3: kvm-userland-virtio-scsi-passthrough --]
[-- Type: text/plain, Size: 6193 bytes --]
virtio: Implement SCSI passthrough for virtio-blk
This patch implements SCSI passthrough handling for Qemu/KVM.
It's actually quite simple; just construct a SG header and
call SG_IO ioctl on the underlying block device. But we have
to make sure to map the result and error codes correctly upon
return.
Signed-off-by: Hannes Reinecke <hare@suse.de>
diff --git a/qemu/hw/virtio-blk.c b/qemu/hw/virtio-blk.c
index 88dc086..53608b7 100644
--- a/qemu/hw/virtio-blk.c
+++ b/qemu/hw/virtio-blk.c
@@ -16,6 +16,54 @@
#include "block_int.h"
#include "pc.h"
+/* from Linux's scsi/sg.h */
+
+typedef struct sg_iovec /* same structure as used by readv() Linux system */
+{ /* call. It defines one scatter-gather element. */
+ void __user *iov_base; /* Starting address */
+ size_t iov_len; /* Length in bytes */
+} sg_iovec_t;
+
+typedef struct sg_io_hdr
+{
+ int interface_id; /* [i] 'S' for SCSI generic (required) */
+ int dxfer_direction; /* [i] data transfer direction */
+ unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
+ unsigned char mx_sb_len; /* [i] max length to write to sbp */
+ unsigned short iovec_count; /* [i] 0 implies no scatter gather */
+ unsigned int dxfer_len; /* [i] byte count of data transfer */
+ void __user *dxferp; /* [i], [*io] points to data transfer memory
+ or scatter gather list */
+ unsigned char __user *cmdp; /* [i], [*i] points to command to perform */
+ void __user *sbp; /* [i], [*o] points to sense_buffer memory */
+ unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
+ unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */
+ int pack_id; /* [i->o] unused internally (normally) */
+ void __user * usr_ptr; /* [i->o] unused internally */
+ unsigned char status; /* [o] scsi status */
+ unsigned char masked_status;/* [o] shifted, masked scsi status */
+ unsigned char msg_status; /* [o] messaging level data (optional) */
+ unsigned char sb_len_wr; /* [o] byte count actually written to sbp */
+ unsigned short host_status; /* [o] errors from host adapter */
+ unsigned short driver_status;/* [o] errors from software driver */
+ int resid; /* [o] dxfer_len - actual_transferred */
+ unsigned int duration; /* [o] time taken by cmd (unit: millisec) */
+ unsigned int info; /* [o] auxiliary information */
+} sg_io_hdr_t; /* 64 bytes long (on i386) */
+
+#define SG_IO 0x2285
+#define SG_INTERFACE_ID_ORIG 'S'
+
+/* Use negative values to flag difference from original sg_header structure */
+#define SG_DXFER_NONE (-1) /* e.g. a SCSI Test Unit Ready command */
+#define SG_DXFER_TO_DEV (-2) /* e.g. a SCSI WRITE command */
+#define SG_DXFER_FROM_DEV (-3) /* e.g. a SCSI READ command */
+#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
+ additional property than during indirect
+ IO the user buffer is copied into the
+ kernel buffers before the transfer */
+#define SG_DXFER_UNKNOWN (-5) /* Unknown data direction */
+
/* from Linux's linux/virtio_blk.h */
/* The ID for virtio_block */
@@ -62,12 +110,21 @@ struct virtio_blk_outhdr
#define VIRTIO_BLK_S_IOERR 1
#define VIRTIO_BLK_S_UNSUPP 2
-/* This is the first element of the write scatter-gather list */
+/* This is the last element of the write scatter-gather list */
struct virtio_blk_inhdr
{
unsigned char status;
};
+/* SCSI pass-through header */
+struct virtio_scsi_inhdr
+{
+ unsigned int errors;
+ unsigned int data_len;
+ unsigned int sense_len;
+ unsigned int residual;
+};
+
typedef struct VirtIOBlock
{
VirtIODevice vdev;
@@ -86,6 +143,7 @@ typedef struct VirtIOBlockReq
VirtQueueElement elem;
struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr *out;
+ struct virtio_scsi_inhdr *scsi;
size_t size;
uint8_t *buffer;
} VirtIOBlockReq;
@@ -162,10 +220,62 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
- unsigned int len = sizeof(*req->in);
+ /* Construct sg header */
+ struct sg_io_hdr hdr;
+ int ret, size = 0;
+
+ memset(&hdr, 0, sizeof(struct sg_io_hdr));
+ hdr.interface_id = 'S';
+ hdr.cmd_len = req->elem.out_sg[1].iov_len;
+ hdr.cmdp = req->elem.out_sg[1].iov_base;
+ hdr.dxfer_len = 0;
+ hdr.dxfer_direction = SG_DXFER_NONE;
+
+ if (req->elem.out_num < 2 || req->elem.in_num < 3) {
+ req->in->status = VIRTIO_BLK_S_IOERR;
+ goto out_scsi;
+ }
+ req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
+ size = sizeof(*req->in) + sizeof(*req->scsi);
+
+ if (req->elem.out_num > 2) {
+ hdr.dxfer_direction = SG_DXFER_TO_DEV;
+ hdr.iovec_count = req->elem.out_num - 2;
- req->in->status = VIRTIO_BLK_S_UNSUPP;
- virtqueue_push(vq, &req->elem, len);
+ for (i = 0; i < hdr.iovec_count; i++)
+ hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
+
+ hdr.dxferp = req->elem.out_sg + 2;
+ } else if (req->elem.in_num > 3) {
+ hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ hdr.iovec_count = req->elem.in_num - 3;
+ for (i = 0; i < hdr.iovec_count; i++)
+ hdr.dxfer_len += req->elem.in_sg[i].iov_len;
+
+ hdr.dxferp = req->elem.in_sg;
+ size += hdr.dxfer_len;
+ }
+ hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
+ hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
+ size += hdr.mx_sb_len;
+
+ ret = bdrv_ioctl(s->bs, SG_IO, &hdr);
+
+ if (ret) {
+ req->in->status = VIRTIO_BLK_S_UNSUPP;
+ hdr.status = ret;
+ hdr.resid = hdr.dxfer_len;
+ } else if (hdr.status)
+ req->in->status = VIRTIO_BLK_S_IOERR;
+ else
+ req->in->status = VIRTIO_BLK_S_OK;
+
+ req->scsi->errors = hdr.status;
+ req->scsi->residual = hdr.resid;
+ req->scsi->sense_len = hdr.sb_len_wr;
+ req->scsi->data_len = hdr.dxfer_len;
+ out_scsi:
+ virtqueue_push(vq, &req->elem, size);
virtio_notify(vdev, vq);
qemu_free(req);
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
2008-08-29 9:28 [RFC] [PATCH] SCSI passthrough for virtio-blk Hannes Reinecke
@ 2008-08-29 11:01 ` Christian Borntraeger
2008-08-29 11:47 ` Hannes Reinecke
0 siblings, 1 reply; 7+ messages in thread
From: Christian Borntraeger @ 2008-08-29 11:01 UTC (permalink / raw)
To: Hannes Reinecke; +Cc: kvm, virtualization
Am Freitag, 29. August 2008 schrieb Hannes Reinecke:
> So when using '-drive file=/dev/sgXX,if=virtio,format=host_device' you
> can happily call any sg_XX command on the resulting vdX device. Quite
> neat, methinks. And it's even backwards compatible, so each of these
> patches should work without the other one applied.
Does not work here. If the host does not support the pass-through, the device
drivers waits for an response. I tried sdparm /dev/vda with a patched kernel
and an unpatched userspace.
I think you should use a feature bit to avoid problems.
Christian
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
2008-08-29 11:01 ` Christian Borntraeger
@ 2008-08-29 11:47 ` Hannes Reinecke
2008-08-29 12:00 ` Christian Borntraeger
0 siblings, 1 reply; 7+ messages in thread
From: Hannes Reinecke @ 2008-08-29 11:47 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: virtualization, kvm
Hi Christian,
Christian Borntraeger wrote:
> Am Freitag, 29. August 2008 schrieb Hannes Reinecke:
>> So when using '-drive file=/dev/sgXX,if=virtio,format=host_device' you
>> can happily call any sg_XX command on the resulting vdX device. Quite
>> neat, methinks. And it's even backwards compatible, so each of these
>> patches should work without the other one applied.
>
> Does not work here. If the host does not support the pass-through, the device
> drivers waits for an response. I tried sdparm /dev/vda with a patched kernel
> and an unpatched userspace.
>
Hmm. Works here, using an unpatched kvm-73.
Which version did you use?
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
2008-08-29 11:47 ` Hannes Reinecke
@ 2008-08-29 12:00 ` Christian Borntraeger
2008-08-29 12:04 ` Hannes Reinecke
0 siblings, 1 reply; 7+ messages in thread
From: Christian Borntraeger @ 2008-08-29 12:00 UTC (permalink / raw)
To: Hannes Reinecke; +Cc: virtualization, kvm
Am Freitag, 29. August 2008 schrieb Hannes Reinecke:
> Hmm. Works here, using an unpatched kvm-73.
> Which version did you use?
I use the s390 userspace prototype kuli which uses an virtio transport similar
to lguest.
I retried and it seems to race. Most of the time it works fine, but sometimes
sdparm hangs. I will have a 2nd look.
sysrq-t gives me the following trace:
Call Trace:
([<040000000755bc78>] 0x40000000755bc78)
sdparm D 000000000043659e 0 2493 1
000000000012004a 000000000744f740 000000000744f778 001896469fd23785
000000000744f778 00000000009e5500 000000000043f230 0000000000120130
000000000744f778 0000000006d39400 0000000006d39f80 0000000000000001
00000000009e6f00 00000000076bf8e8 000000000744f7c8 0000000007530670
000000000043f610 0000000000435e66 000000000744f7c8 000000000744f868
Call Trace:
([<0000000000435e66>] schedule+0x32e/0x7ec)
[<000000000043659e>] schedule_timeout+0xba/0x10c
[<00000000004358da>] wait_for_common+0xbe/0x1a8
[<000000000027ec3e>] blk_execute_rq+0x86/0xc4
[<0000000000282768>] sg_io+0x1a4/0x360
[<0000000000282f8c>] scsi_cmd_ioctl+0x2bc/0x3f0
[<00000000002c3108>] virtblk_ioctl+0x44/0x58
[<000000000027ff18>] blkdev_driver_ioctl+0x98/0xa4
[<000000000027ffd8>] blkdev_ioctl+0xb4/0x7f8
[<00000000001e1572>] block_ioctl+0x3a/0x48
[<00000000001bca0a>] vfs_ioctl+0x52/0xdc
[<00000000001bcb0a>] do_vfs_ioctl+0x76/0x350
[<00000000001bce6e>] sys_ioctl+0x8a/0xa0
[<000000000011282c>] sysc_tracego+0xe/0x14
[<0000020000114286>] 0x20000114286
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
2008-08-29 12:00 ` Christian Borntraeger
@ 2008-08-29 12:04 ` Hannes Reinecke
2008-08-29 12:48 ` Christian Borntraeger
2008-08-29 13:18 ` Christian Borntraeger
0 siblings, 2 replies; 7+ messages in thread
From: Hannes Reinecke @ 2008-08-29 12:04 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: virtualization, kvm
Hi Christian,
Christian Borntraeger wrote:
> Am Freitag, 29. August 2008 schrieb Hannes Reinecke:
>> Hmm. Works here, using an unpatched kvm-73.
>> Which version did you use?
>
> I use the s390 userspace prototype kuli which uses an virtio transport similar
> to lguest.
>
> I retried and it seems to race. Most of the time it works fine, but sometimes
> sdparm hangs. I will have a 2nd look.
>
> sysrq-t gives me the following trace:
>
> Call Trace:
> ([<040000000755bc78>] 0x40000000755bc78)
> sdparm D 000000000043659e 0 2493 1
> 000000000012004a 000000000744f740 000000000744f778 001896469fd23785
> 000000000744f778 00000000009e5500 000000000043f230 0000000000120130
> 000000000744f778 0000000006d39400 0000000006d39f80 0000000000000001
> 00000000009e6f00 00000000076bf8e8 000000000744f7c8 0000000007530670
> 000000000043f610 0000000000435e66 000000000744f7c8 000000000744f868
> Call Trace:
> ([<0000000000435e66>] schedule+0x32e/0x7ec)
> [<000000000043659e>] schedule_timeout+0xba/0x10c
> [<00000000004358da>] wait_for_common+0xbe/0x1a8
> [<000000000027ec3e>] blk_execute_rq+0x86/0xc4
> [<0000000000282768>] sg_io+0x1a4/0x360
> [<0000000000282f8c>] scsi_cmd_ioctl+0x2bc/0x3f0
> [<00000000002c3108>] virtblk_ioctl+0x44/0x58
> [<000000000027ff18>] blkdev_driver_ioctl+0x98/0xa4
> [<000000000027ffd8>] blkdev_ioctl+0xb4/0x7f8
> [<00000000001e1572>] block_ioctl+0x3a/0x48
> [<00000000001bca0a>] vfs_ioctl+0x52/0xdc
> [<00000000001bcb0a>] do_vfs_ioctl+0x76/0x350
> [<00000000001bce6e>] sys_ioctl+0x8a/0xa0
> [<000000000011282c>] sysc_tracego+0xe/0x14
> [<0000020000114286>] 0x20000114286
I'm tempted to say 'not my fault'; the submitted SCSI request on
the _host_ hangs and doesn't come back.
Looks more like a SCSI problem on the host ...
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
2008-08-29 12:04 ` Hannes Reinecke
@ 2008-08-29 12:48 ` Christian Borntraeger
2008-08-29 13:18 ` Christian Borntraeger
1 sibling, 0 replies; 7+ messages in thread
From: Christian Borntraeger @ 2008-08-29 12:48 UTC (permalink / raw)
To: Hannes Reinecke; +Cc: virtualization, kvm
Am Freitag, 29. August 2008 schrieb Hannes Reinecke:
> > ([<0000000000435e66>] schedule+0x32e/0x7ec)
> > [<000000000043659e>] schedule_timeout+0xba/0x10c
> > [<00000000004358da>] wait_for_common+0xbe/0x1a8
> > [<000000000027ec3e>] blk_execute_rq+0x86/0xc4
> > [<0000000000282768>] sg_io+0x1a4/0x360
> > [<0000000000282f8c>] scsi_cmd_ioctl+0x2bc/0x3f0
> > [<00000000002c3108>] virtblk_ioctl+0x44/0x58
> > [<000000000027ff18>] blkdev_driver_ioctl+0x98/0xa4
> > [<000000000027ffd8>] blkdev_ioctl+0xb4/0x7f8
> > [<00000000001e1572>] block_ioctl+0x3a/0x48
> > [<00000000001bca0a>] vfs_ioctl+0x52/0xdc
> > [<00000000001bcb0a>] do_vfs_ioctl+0x76/0x350
> > [<00000000001bce6e>] sys_ioctl+0x8a/0xa0
> > [<000000000011282c>] sysc_tracego+0xe/0x14
> > [<0000020000114286>] 0x20000114286
>
> I'm tempted to say 'not my fault'; the submitted SCSI request on
> the _host_ hangs and doesn't come back.
> Looks more like a SCSI problem on the host ...
It is a guest process trace.
Anyway, after you suggested to look at the len field it appeared to me, that
the new code sets the data_len, sense_len and changes the number of reported
bytes to random values even if the host returns VIRTIO_BLK_S_UNSUPP.
Moving these assignments to the VIRTIO_BLK_S_OK case seems to fix it.
Can you test if SG_IO still works for you after applying this patch:
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
drivers/block/virtio_blk.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
Index: kvm/drivers/block/virtio_blk.c
===================================================================
--- kvm.orig/drivers/block/virtio_blk.c
+++ kvm/drivers/block/virtio_blk.c
@@ -50,9 +50,17 @@ static void blk_done(struct virtqueue *v
while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
int error;
unsigned int bytes;
+
+ bytes = blk_rq_bytes(vbr->req);
switch (vbr->status) {
case VIRTIO_BLK_S_OK:
error = 0;
+ if (blk_pc_request(vbr->req)) {
+ vbr->req->data_len = vbr->in_hdr.residual;
+ bytes = vbr->in_hdr.data_len;
+ vbr->req->sense_len = vbr->in_hdr.sense_len;
+ vbr->req->errors = vbr->in_hdr.status;
+ }
break;
case VIRTIO_BLK_S_UNSUPP:
error = -ENOTTY;
@@ -61,15 +69,6 @@ static void blk_done(struct virtqueue *v
error = -EIO;
break;
}
-
- if (blk_pc_request(vbr->req)) {
- vbr->req->data_len = vbr->in_hdr.residual;
- bytes = vbr->in_hdr.data_len;
- vbr->req->sense_len = vbr->in_hdr.sense_len;
- vbr->req->errors = vbr->in_hdr.status;
- } else
- bytes = blk_rq_bytes(vbr->req);
-
__blk_end_request(vbr->req, error, bytes);
list_del(&vbr->list);
mempool_free(vbr, vblk->pool);
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
2008-08-29 12:04 ` Hannes Reinecke
2008-08-29 12:48 ` Christian Borntraeger
@ 2008-08-29 13:18 ` Christian Borntraeger
1 sibling, 0 replies; 7+ messages in thread
From: Christian Borntraeger @ 2008-08-29 13:18 UTC (permalink / raw)
To: virtualization; +Cc: Hannes Reinecke, kvm
Thanks for your feedback.
Here is a second try to allows to propagate scsi error code from host->guest.
Makes sense?
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
drivers/block/virtio_blk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: kvm/drivers/block/virtio_blk.c
===================================================================
--- kvm.orig/drivers/block/virtio_blk.c
+++ kvm/drivers/block/virtio_blk.c
@@ -62,7 +62,7 @@ static void blk_done(struct virtqueue *v
break;
}
- if (blk_pc_request(vbr->req)) {
+ if (blk_pc_request(vbr->req) && len >= sizeof(vbr->in_hdr)) {
vbr->req->data_len = vbr->in_hdr.residual;
bytes = vbr->in_hdr.data_len;
vbr->req->sense_len = vbr->in_hdr.sense_len;
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2008-08-29 13:20 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-29 9:28 [RFC] [PATCH] SCSI passthrough for virtio-blk Hannes Reinecke
2008-08-29 11:01 ` Christian Borntraeger
2008-08-29 11:47 ` Hannes Reinecke
2008-08-29 12:00 ` Christian Borntraeger
2008-08-29 12:04 ` Hannes Reinecke
2008-08-29 12:48 ` Christian Borntraeger
2008-08-29 13:18 ` Christian Borntraeger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox