[RFC] [PATCH] SCSI passthrough for virtio-blk
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 [EMAIL PROTECTED] +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg) 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 [EMAIL PROTECTED] 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
Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
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 -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
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 [EMAIL PROTECTED] +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg) -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
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: ([04000755bc78] 0x4000755bc78) sdparmD 0043659e 0 2493 1 0012004a 0744f740 0744f778 001896469fd23785 0744f778 009e5500 0043f230 00120130 0744f778 06d39400 06d39f80 0001 009e6f00 076bf8e8 0744f7c8 07530670 0043f610 00435e66 0744f7c8 0744f868 Call Trace: ([00435e66] schedule+0x32e/0x7ec) [0043659e] schedule_timeout+0xba/0x10c [004358da] wait_for_common+0xbe/0x1a8 [0027ec3e] blk_execute_rq+0x86/0xc4 [00282768] sg_io+0x1a4/0x360 [00282f8c] scsi_cmd_ioctl+0x2bc/0x3f0 [002c3108] virtblk_ioctl+0x44/0x58 [0027ff18] blkdev_driver_ioctl+0x98/0xa4 [0027ffd8] blkdev_ioctl+0xb4/0x7f8 [001e1572] block_ioctl+0x3a/0x48 [001bca0a] vfs_ioctl+0x52/0xdc [001bcb0a] do_vfs_ioctl+0x76/0x350 [001bce6e] sys_ioctl+0x8a/0xa0 [0011282c] sysc_tracego+0xe/0x14 [02114286] 0x2114286 -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
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: ([04000755bc78] 0x4000755bc78) sdparmD 0043659e 0 2493 1 0012004a 0744f740 0744f778 001896469fd23785 0744f778 009e5500 0043f230 00120130 0744f778 06d39400 06d39f80 0001 009e6f00 076bf8e8 0744f7c8 07530670 0043f610 00435e66 0744f7c8 0744f868 Call Trace: ([00435e66] schedule+0x32e/0x7ec) [0043659e] schedule_timeout+0xba/0x10c [004358da] wait_for_common+0xbe/0x1a8 [0027ec3e] blk_execute_rq+0x86/0xc4 [00282768] sg_io+0x1a4/0x360 [00282f8c] scsi_cmd_ioctl+0x2bc/0x3f0 [002c3108] virtblk_ioctl+0x44/0x58 [0027ff18] blkdev_driver_ioctl+0x98/0xa4 [0027ffd8] blkdev_ioctl+0xb4/0x7f8 [001e1572] block_ioctl+0x3a/0x48 [001bca0a] vfs_ioctl+0x52/0xdc [001bcb0a] do_vfs_ioctl+0x76/0x350 [001bce6e] sys_ioctl+0x8a/0xa0 [0011282c] sysc_tracego+0xe/0x14 [02114286] 0x2114286 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 [EMAIL PROTECTED] +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg) -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] [PATCH] SCSI passthrough for virtio-blk
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 [EMAIL PROTECTED] --- 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; -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html