ISCSI: Add SCSI passthrough via scsi-generic to libiscsi

Update iscsi to allow passthrough of SG_IO scsi commands when the iscsi
device is forced to be scsi-generic.

Implement both bdrv_ioctl() and bdrv_aio_ioctl() in the iscsi backend,
emulate the SG_IO ioctl and pass the SCSI commands across to the
iscsi target.

This allows end-to-end passthrough of SCSI all the way from the guest,
to qemu, via scsi-generic, then libiscsi all the way to the iscsi target.

To activate this you need to specify that the iscsi lun should be treated
as a scsi-generic device.

Example:
    -device lsi -device scsi-generic,drive=MyISCSI \
    -drive file=iscsi://10.1.1.125/iqn.ronnie.test/1,if=none,id=MyISCSI

Note, you can currently not boot a qemu guest from a scsi device.

Note,
This only works when the host is linux, since the emulation relies on
definitions of SG_IO from the scsi-generic implementation in the
linux kernel.
It should be fairly easy to re-implement some structures similar enough
for non-linux hosts to do the same style of passthrough via a fake
scsi generic layer and libiscsi if need be.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Ronnie Sahlberg 2012-05-25 21:59:01 +10:00 committed by Paolo Bonzini
parent 1a4f0c3a06
commit 983924532f
2 changed files with 147 additions and 8 deletions

View file

@ -400,12 +400,6 @@ static int scsi_generic_initfn(SCSIDevice *s)
return -1;
}
/* check we are really using a /dev/sg* file */
if (!bdrv_is_sg(s->conf.bs)) {
error_report("not /dev/sg*");
return -1;
}
if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
error_report("Device doesn't support drive option werror");
return -1;
@ -416,8 +410,11 @@ static int scsi_generic_initfn(SCSIDevice *s)
}
/* check we are using a driver managing SG_IO (version 3 and after */
if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
sg_version < 30000) {
if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) {
error_report("scsi generic interface not supported");
return -1;
}
if (sg_version < 30000) {
error_report("scsi generic interface too old");
return -1;
}