Real SCSI device passthrough
cover Real SCSI device passthrough
This series of patches allows to connect real SCSI device to the virtual SCSI controller of Qemu using the SCSI Generic interface (/dev/sg)
for instance:
qemu -hda my_disk.qcow2 -drive file=/dev/sg3,if=scsi
[PATCH 1/2] SCSI cleanup
This patch reworks the interface between SCSI controller and SCSI device.
[PATCH 2/2] Real SCSI device passthrough (v3)
This patch allows to connect the virtual SCSI interface of Qemu to a real SCSI device of the host.
Laurent
PATCH 1/2 SCSI cleanup
This patch reworks the interface between SCSI controller and SCSI device. It allows to connect something else than scsi-disk.c to the SCSI controller.
It is needed to use SCSI passthrough patch.
Laurent
--- hw/esp.c | 16 +++++++------- hw/lsi53c895a.c | 41 ++++++++++++++++++++++++------------- hw/scsi-disk.c | 62 ++++++++++++++++++++++++++++++++++---------------------- hw/scsi-disk.h | 27 ++++++++++++------------ hw/usb-msd.c | 16 +++++++------- 5 files changed, 95 insertions(+), 67 deletions(-)
hw/scsi-disk.c +38 -24
@@ -37,7 +37,7 @@ do { fprintf(stderr, "scsi-disk: " fmt ,#define SCSI_DMA_BUF_SIZE 65536 typedef struct SCSIRequest { - SCSIDevice *dev; + SCSIDeviceState *dev; uint32_t tag; /* ??? We should probably keep track of whether the data trasfer is a read or a write. Currently we rely on the host getting it right. */
@@ -51,7 +51,7 @@ typedef struct SCSIRequest {struct SCSIRequest *next; } SCSIRequest; -struct SCSIDevice +struct SCSIDeviceState {BlockDriverState *bdrv;SCSIRequest *requests;
@@ -69,7 +69,7 @@ struct SCSIDevice/* Global pool of SCSIRequest structures. */ static SCSIRequest *free_requests =NULL ; -static SCSIRequest *scsi_new_request (SCSIDevice *s,uint32_t tag) +static SCSIRequest *scsi_new_request (SCSIDeviceState *s,uint32_t tag) {SCSIRequest *r;
@@ -94,7 +94,7 @@ static SCSIRequest *scsi_new_request(SCSstatic void scsi_remove_request (SCSIRequest *r) {SCSIRequest *last; -SCSIDevice *s = r->dev; +SCSIDeviceState *s = r->dev;if (s->requests == r) { s->requests = r->next;
@@ -112,7 +112,7 @@ static void scsi_remove_request(SCSIRequ free_requests = r; } -static SCSIRequest *scsi_find_request (SCSIDevice *s,uint32_t tag) +static SCSIRequest *scsi_find_request (SCSIDeviceState *s,uint32_t tag) {SCSIRequest *r;
@@ -126,7 +126,7 @@ static SCSIRequest *scsi_find_request(SC/* Helper function for command completion. */ static void scsi_command_complete (SCSIRequest *r,int sense) { -SCSIDevice *s = r->dev; +SCSIDeviceState *s = r->dev;uint32_t tag;DPRINTF ("Command complete tag=0x%x sense=%d\n" , r->tag, sense); s->sense = sense;
@@ -136,8 +136,9 @@ static void scsi_command_complete(SCSIRe }/* Cancel a pending data transfer. */ -void scsi_cancel_io (SCSIDevice *s,uint32_t tag) +static void scsi_cancel_io (SCSIDevice *d,uint32_t tag) { +SCSIDeviceState *s = d->state;SCSIRequest *r;DPRINTF ("Cancel tag=0x%x\n" , tag); r =scsi_find_request (s, tag);
@@ -152,7 +153,7 @@ void scsi_cancel_io(SCSIDevice *s, uint3static void scsi_read_complete (void * opaque,int ret) {SCSIRequest *r = (SCSIRequest *)opaque; -SCSIDevice *s = r->dev; +SCSIDeviceState *s = r->dev;if (ret) {DPRINTF ("IO error\n" );
@@ -165,8 +166,9 @@ static void scsi_read_complete(void * op }/* Read more data from scsi device into buffer. */ -void scsi_read_data (SCSIDevice *s,uint32_t tag) +static void scsi_read_data (SCSIDevice *d,uint32_t tag) { +SCSIDeviceState *s = d->state;SCSIRequest *r;uint32_t n;
@@ -205,7 +207,7 @@ void scsi_read_data(SCSIDevice *s, uint3static void scsi_write_complete (void * opaque,int ret) {SCSIRequest *r = (SCSIRequest *)opaque; -SCSIDevice *s = r->dev; +SCSIDeviceState *s = r->dev;uint32_t len;if (ret) {
@@ -229,8 +231,9 @@ static void scsi_write_complete(void * o/* Write data to a scsi device. Returns nonzero on failure. The transfer may complete asynchronously. */ -int scsi_write_data (SCSIDevice *s,uint32_t tag) +static int scsi_write_data (SCSIDevice *d,uint32_t tag) { +SCSIDeviceState *s = d->state;SCSIRequest *r;uint32_t n;
@@ -260,8 +263,9 @@ int scsi_write_data(SCSIDevice *s, uint3 }/* Return a pointer to the data buffer. */ -uint8_t *scsi_get_buf (SCSIDevice *s,uint32_t tag) +static uint8_t *scsi_get_buf (SCSIDevice *d,uint32_t tag) { +SCSIDeviceState *s = d->state;SCSIRequest *r; r =scsi_find_request (s, tag);
@@ -277,8 +281,10 @@ uint8_t *scsi_get_buf(SCSIDevice *s, uin(eg. disk reads), negative for transfers to the device (eg. disk writes), and zero if the command does not transfer any data. */ -int32_t scsi_send_command (SCSIDevice *s,uint32_t tag,uint8_t *buf,int lun) +static int32_t scsi_send_command (SCSIDevice *d,uint32_t tag, +uint8_t *buf,int lun) { +SCSIDeviceState *s = d->state;int64_t nb_sectors;uint32_t lba;uint32_t len;
@@ -292,7 +298,7 @@ int32_t scsi_send_command(SCSIDevice *s, r =scsi_find_request (s, tag);if (r) {BADF ("Tag 0x%x already in use\n" , tag); -scsi_cancel_io (s, tag); +scsi_cancel_io (d, tag); }/* ??? Tags are not unique for different luns. We only implement a single lun, so this should not matter. */
@@ -577,19 +583,19 @@ int32_t scsi_send_command(SCSIDevice *s, } } -void scsi_disk_destroy (SCSIDevice *s) +static void scsi_destroy (SCSIDevice *d) { -qemu_free (s); +qemu_free (d->state); +qemu_free (d); } -SCSIDevice *scsi_disk_init (BlockDriverState *bdrv, -int tcq, -scsi_completionfn completion, -void *opaque) +SCSIDevice *scsi_disk_init (BlockDriverState *bdrv,int tcq, +scsi_completionfn completion,void *opaque) { -SCSIDevice *s; +SCSIDevice *d; +SCSIDeviceState *s; - s = (SCSIDevice *)qemu_mallocz (sizeof (SCSIDevice)); + s = (SCSIDeviceState *)qemu_mallocz (sizeof (SCSIDeviceState)); s->bdrv = bdrv; s->tcq = tcq; s->completion = completion;
@@ -600,6 +606,14 @@ SCSIDevice *scsi_disk_init(BlockDriverSt s->cluster_size =1 ; } -return s; -} + d = (SCSIDevice *)qemu_mallocz (sizeof (SCSIDevice)); + d->state = s; + d->destroy = scsi_destroy; + d->send_command = scsi_send_command; + d->read_data = scsi_read_data; + d->write_data = scsi_write_data; + d->cancel_io = scsi_cancel_io; + d->get_buf = scsi_get_buf; +return d; +}
hw/esp.c +8 -8
@@ -165,7 +165,7 @@ static int get_cmd(ESPState *s, uint8_tif (s->current_dev) {/* Started a new command before the old one finished. Cancel it. */ -scsi_cancel_io (s->current_dev,0 ); + s->current_dev->cancel_io (s->current_dev,0 ); s->async_len =0 ; }
@@ -188,7 +188,7 @@ static void do_cmd(ESPState *s, uint8_tDPRINTF ("do_cmd: busid 0x%x\n" , buf[0 ]); lun = buf[0 ] &7 ; - datalen =scsi_send_command (s->current_dev,0 , &buf[1 ], lun); + datalen = s->current_dev->send_command (s->current_dev,0 , &buf[1 ], lun); s->ti_size = datalen;if (datalen !=0 ) { s->rregs[ESP_RSTAT ] =STAT_IN |STAT_TC ;
@@ -196,10 +196,10 @@ static void do_cmd(ESPState *s, uint8_t s->dma_counter =0 ;if (datalen >0 ) { s->rregs[ESP_RSTAT ] |=STAT_DI ; -scsi_read_data (s->current_dev,0 ); + s->current_dev->read_data (s->current_dev,0 ); }else { s->rregs[ESP_RSTAT ] |=STAT_DO ; -scsi_write_data (s->current_dev,0 ); + s->current_dev->write_data (s->current_dev,0 ); } } s->rregs[ESP_RINTR ] =INTR_BS |INTR_FC ;
@@ -298,9 +298,9 @@ static void esp_do_dma(ESPState *s)if (s->async_len ==0 ) {if (to_device) {// ti_size is negative -scsi_write_data (s->current_dev,0 ); + s->current_dev->write_data (s->current_dev,0 ); }else { -scsi_read_data (s->current_dev,0 ); + s->current_dev->read_data (s->current_dev,0 );/* If there is still data to be read from the device then complete the DMA operation immeriately. Otherwise defer until the scsi layer has completed. */
@@ -335,7 +335,7 @@ static void esp_command_complete(void *o }else {DPRINTF ("transfer %d/%d\n" , s->dma_left, s->ti_size); s->async_len = arg; - s->async_buf =scsi_get_buf (s->current_dev,0 ); + s->async_buf = s->current_dev->get_buf (s->current_dev,0 );if (s->dma_left) {esp_do_dma (s); }else if (s->dma_counter !=0 && s->ti_size <=0 ) {
@@ -611,7 +611,7 @@ void esp_scsi_attach(void *opaque, Block }if (s->scsi_dev[id]) {DPRINTF ("Destroying device %d\n" , id); -scsi_disk_destroy (s->scsi_dev[id]); + s->scsi_dev[id]->destroy (s->scsi_dev[id]); }DPRINTF ("Attaching block device %d\n" , id);/* Command queueing is not implemented. */
hw/lsi53c895a.c +27 -14
90 lines not on this page · raw message
hw/usb-msd.c +8 -8
@@ -149,9 +149,9 @@ static void usb_msd_copy_data(MSDState * s->data_len -= len;if (s->scsi_len ==0 ) {if (s->mode ==USB_MSDM_DATAIN ) { -scsi_read_data (s->scsi_dev, s->tag); + s->scsi_dev->read_data (s->scsi_dev, s->tag); }else if (s->mode ==USB_MSDM_DATAOUT ) { -scsi_write_data (s->scsi_dev, s->tag); + s->scsi_dev->write_data (s->scsi_dev, s->tag); } } }
@@ -204,7 +204,7 @@ static void usb_msd_command_complete(voireturn ; } s->scsi_len = arg; - s->scsi_buf =scsi_get_buf (s->scsi_dev, tag); + s->scsi_buf = s->scsi_dev->get_buf (s->scsi_dev, tag);if (p) {usb_msd_copy_data (s);if (s->usb_len ==0 ) {
@@ -342,7 +342,7 @@ static int usb_msd_handle_control(USBDevstatic void usb_msd_cancel_io (USBPacket *p,void *opaque) {MSDState *s = opaque; -scsi_cancel_io (s->scsi_dev, s->tag); + s->scsi_dev->cancel_io (s->scsi_dev, s->tag); s->packet =NULL ; s->scsi_len =0 ; }
@@ -390,14 +390,14 @@ static int usb_msd_handle_data(USBDeviceDPRINTF ("Command tag 0x%x flags %08x len %d data %d\n" , s->tag, cbw.flags, cbw.cmd_len, s->data_len); s->residue =0 ; -scsi_send_command (s->scsi_dev, s->tag, cbw.cmd,0 ); + s->scsi_dev->send_command (s->scsi_dev, s->tag, cbw.cmd,0 );/* ??? Should check that USB and SCSI data transfer directions match. */ if (s->residue ==0 ) {if (s->mode ==USB_MSDM_DATAIN ) { -scsi_read_data (s->scsi_dev, s->tag); + s->scsi_dev->read_data (s->scsi_dev, s->tag); }else if (s->mode ==USB_MSDM_DATAOUT ) { -scsi_write_data (s->scsi_dev, s->tag); + s->scsi_dev->write_data (s->scsi_dev, s->tag); } } ret = len;
@@ -508,7 +508,7 @@ static void usb_msd_handle_destroy(USBDe {MSDState *s = (MSDState *)dev; -scsi_disk_destroy (s->scsi_dev); + s->scsi_dev->destroy (s->scsi_dev);bdrv_delete (s->bs);qemu_free (s); }
hw/scsi-disk.h +14 -13
@@ -7,24 +7,25 @@ enum scsi_reason {SCSI_REASON_DATA /* Transfer complete, more data required. */ }; +typedef struct SCSIDeviceState SCSIDeviceState ;typedef struct SCSIDevice SCSIDevice ;typedef void (*scsi_completionfn )(void *opaque,int reason,uint32_t tag,uint32_t arg); -SCSIDevice *scsi_disk_init (BlockDriverState *bdrv, -int tcq, -scsi_completionfn completion, -void *opaque); -void scsi_disk_destroy (SCSIDevice *s); +struct SCSIDevice +{ +SCSIDeviceState *state; +void (*destroy)(SCSIDevice *s); +int32_t (*send_command)(SCSIDevice *s,uint32_t tag,uint8_t *buf, +int lun); +void (*read_data)(SCSIDevice *s,uint32_t tag); +int (*write_data)(SCSIDevice *s,uint32_t tag); +void (*cancel_io)(SCSIDevice *s,uint32_t tag); +uint8_t *(*get_buf)(SCSIDevice *s,uint32_t tag); +}; -int32_t scsi_send_command (SCSIDevice *s,uint32_t tag,uint8_t *buf,int lun); -/* SCSI data transfers are asynchrnonous. However, unlike the block IO -layer the completion routine may be called directly by -scsi_{read,write}_data. */ -void scsi_read_data (SCSIDevice *s,uint32_t tag); -int scsi_write_data (SCSIDevice *s,uint32_t tag); -void scsi_cancel_io (SCSIDevice *s,uint32_t tag); -uint8_t *scsi_get_buf (SCSIDevice *s,uint32_t tag); +SCSIDevice *scsi_disk_init (BlockDriverState *bdrv,int tcq, +scsi_completionfn completion,void *opaque);/* cdrom.c */ int cdrom_read_toc (int nb_sectors,uint8_t *buf,int msf,int start_track);
PATCH 2/2 Real SCSI device passthrough (v3)
This patch allows to connect the virtual SCSI interface of Qemu to a real SCSI device of the host.
Using the devices /dev/sg, it allows to send the SCSI commands from the virtual SCSI interface to the real device.
It has been tested with a SATA disk and an ATA CD burner with ide-scsi module and wodim to burn a CD-RW.
v3 has moved SCSI clenup to a separate patch.
Laurent
--- Makefile | 1 block-raw.c | 23 + block.c | 16 + block.h | 2 block_int.h | 4 hw/esp.c | 4 hw/lsi53c895a.c | 8 hw/scsi-disk.h | 2 hw/scsi-generic.c | 667 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 722 insertions(+), 5 deletions(-)
block-raw.c +20 -3
@@ -152,7 +152,7 @@ static int raw_pread(BlockDriverState *bif (ret <0 )return ret; -if (lseek (s->fd, offset,SEEK_SET ) == (off_t)-1 ) { +if (offset >=0 &&lseek (s->fd, offset,SEEK_SET ) == (off_t)-1 ) { ++(s->lseek_err_cnt);if (s->lseek_err_cnt <=10 ) { DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
@@ -205,7 +205,7 @@ static int raw_pwrite(BlockDriverState *if (ret <0 )return ret; -if (lseek (s->fd, offset,SEEK_SET ) == (off_t)-1 ) { +if (offset >=0 &&lseek (s->fd, offset,SEEK_SET ) == (off_t)-1 ) { ++(s->lseek_err_cnt);if (s->lseek_err_cnt) { DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
@@ -388,7 +388,10 @@ static RawAIOCB *raw_aio_setup(BlockDriv acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num; acb->aiocb.aio_sigevent.sigev_notify =SIGEV_SIGNAL ; acb->aiocb.aio_buf = buf; - acb->aiocb.aio_nbytes = nb_sectors *512 ; +if (nb_sectors <0 ) + acb->aiocb.aio_nbytes = -nb_sectors; +else + acb->aiocb.aio_nbytes = nb_sectors *512 ; acb->aiocb.aio_offset = sector_num *512 ; acb->next = first_aio; first_aio = acb;
@@ -680,6 +683,8 @@ static int hdev_open(BlockDriverState *b s->fd_open_flags = open_flags;/* open will not fail even if no floppy is inserted */ open_flags |= O_NONBLOCK; + }else if (strstart (filename,"/dev/sg" ,NULL )) { + bs->sg =1 ; }#endif fd =open (filename, open_flags,0644 );
@@ -859,6 +864,12 @@ static int raw_set_locked(BlockDriverSta return 0; } +static int raw_ioctl (BlockDriverState *bs,unsigned long int req,void *buf) +{ +BDRVRawState *s = bs->opaque; + +return ioctl (s->fd, req, buf); +}#else static int raw_is_inserted (BlockDriverState *bs)
@@ -881,6 +892,10 @@ static int raw_set_locked(BlockDriverStareturn -ENOTSUP ; } +static int raw_ioctl (BlockDriverState *bs,unsigned long int req,void *buf) +{ +return -ENOTSUP ; +}#endif /* !linux */ BlockDriver bdrv_host_device = {
@@ -907,6 +922,8 @@ BlockDriver bdrv_host_device = { .bdrv_media_changed = raw_media_changed, .bdrv_eject = raw_eject, .bdrv_set_locked = raw_set_locked, +/* generic scsi device */ + .bdrv_ioctl = raw_ioctl, };#else /* _WIN32 */
block.c +16 -0
@@ -796,6 +796,11 @@ int bdrv_is_cached(BlockDriverState *bs)return bs->cache; } +int bdrv_is_sg (BlockDriverState *bs) +{ +return bs->sg; +} +/* XXX: no longer used */ void bdrv_set_change_cb (BlockDriverState *bs,void (*change_cb)(void *opaque),void *opaque)
@@ -1404,3 +1409,14 @@ void bdrv_set_locked(BlockDriverState *b drv->bdrv_set_locked (bs, locked); } } + +/* needed for generic scsi interface */ + +int bdrv_ioctl (BlockDriverState *bs,unsigned long int req,void *buf) +{ +BlockDriver *drv = bs->drv; + +if (drv && drv->bdrv_ioctl) +return drv->bdrv_ioctl (bs, req, buf); +return -ENOTSUP ; +}
block.h +2 -0
@@ -120,6 +120,7 @@ int bdrv_get_type_hint(BlockDriverStateint bdrv_get_translation_hint (BlockDriverState *bs);int bdrv_is_removable (BlockDriverState *bs);int bdrv_is_read_only (BlockDriverState *bs); +int bdrv_is_sg (BlockDriverState *bs);int bdrv_is_inserted (BlockDriverState *bs);int bdrv_is_cached (BlockDriverState *bs);int bdrv_media_changed (BlockDriverState *bs);
@@ -150,6 +151,7 @@ int bdrv_snapshot_delete(BlockDriverStatint bdrv_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_info);char *bdrv_snapshot_dump (char *buf,int buf_size,QEMUSnapshotInfo *sn); +int bdrv_ioctl (BlockDriverState *bs,unsigned long int req,void *buf);char *get_human_readable_size (char *buf,int buf_size,int64_t size);int path_is_absolute (const char *path);
block_int.h +4 -0
@@ -82,6 +82,9 @@ struct BlockDriver {int (*bdrv_eject)(BlockDriverState *bs,int eject_flag);int (*bdrv_set_locked)(BlockDriverState *bs,int locked); +/* to control generic scsi devices */ +int (*bdrv_ioctl)(BlockDriverState *bs,unsigned long int req,char *buf); +BlockDriverAIOCB *free_aiocb;struct BlockDriver *next; };
@@ -93,6 +96,7 @@ struct BlockDriverState {int removable;/* if true, the media can be removed */ int locked;/* if true, the media cannot temporarily be ejected */ int encrypted;/* if true, the media is encrypted */ +int sg;/* if true, the device is a /dev/sg* */ /* event callback when inserting/removing */ void (*change_cb)(void *opaque);void *change_opaque;
hw/esp.c +3 -1
@@ -615,7 +615,9 @@ void esp_scsi_attach(void *opaque, Block }DPRINTF ("Attaching block device %d\n" , id);/* Command queueing is not implemented. */ - s->scsi_dev[id] =scsi_disk_init (bd,0 , esp_command_complete, s); + s->scsi_dev[id] =scsi_generic_init (bd,0 , esp_command_complete, s); +if (s->scsi_dev[id] ==NULL ) + s->scsi_dev[id] =scsi_disk_init (bd,0 , esp_command_complete, s); } void *esp_init(target_phys_addr_t espaddr,
hw/lsi53c895a.c +7 -1
@@ -1236,6 +1236,8 @@ static uint8_t lsi_reg_readb(LSIState *sreturn s->sdid;case 0x07 :/* GPREG0 */ return 0x7f ; +case 0x08 :/* Revision ID */ +return 0x00 ;case 0xa :/* SSID */ return s->ssid;case 0xb :/* SBCL */
@@ -1281,6 +1283,8 @@ static uint8_t lsi_reg_readb(LSIState *sreturn s->ctest4;case 0x22 :/* CTEST5 */ return s->ctest5; +case 0x23 :/* CTEST6 */ +return 0 ;case 0x24 :/* DBC[0:7] */ return s->dbc &0xff ;case 0x25 :/* DBC[8:15] */
@@ -1838,7 +1842,9 @@ void lsi_scsi_attach(void *opaque, Block s->scsi_dev[id]->destroy (s->scsi_dev[id]); }DPRINTF ("Attaching block device %d\n" , id); - s->scsi_dev[id] =scsi_disk_init (bd,1 , lsi_command_complete, s); + s->scsi_dev[id] =scsi_generic_init (bd,1 , lsi_command_complete, s); +if (s->scsi_dev[id] ==NULL ) + s->scsi_dev[id] =scsi_disk_init (bd,1 , lsi_command_complete, s); }void *lsi_scsi_init (PCIBus *bus,int devfn)
hw/scsi-generic.c new file +667 -0
667 lines not on this page · raw message
Makefile +1 -0
@@ -56,6 +56,7 @@ OBJS+=irq.o OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o OBJS+=scsi-disk.o cdrom.o +OBJS+=scsi-generic.o OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o OBJS+=sd.o ssi-sd.o
hw/scsi-disk.h +2 -0
@@ -26,6 +26,8 @@ struct SCSIDeviceSCSIDevice *scsi_disk_init (BlockDriverState *bdrv,int tcq,scsi_completionfn completion,void *opaque); +SCSIDevice *scsi_generic_init (BlockDriverState *bdrv,int tcq, +scsi_completionfn completion,void *opaque);/* cdrom.c */ int cdrom_read_toc (int nb_sectors,uint8_t *buf,int msf,int start_track);
Re: [Qemu-devel] [PATCH 2/2] Real SCSI device passthrough (v3)
Quoted 5 lines · Laurent Vivier
- acb->aiocb.aio_nbytes =
nb_sectors* 512;
+ if (nb_sectors< 0)
+ acb->aiocb.aio_nbytes = -nb_sectors;
+ else
+ acb->aiocb.aio_nbytes =nb_sectors* 512;
Ugly hacks like this need at least a decent comment.
Paul
Re: [Qemu-devel] [PATCH 2/2] Real SCSI device passthrough (v3)
Quoted 8 lines · Paul Brook
block-raw.c static RawAIOCB *raw_aio_setup(BlockDriv · line 394
Quoted 5 lines · Laurent Vivier
block-raw.c +4
-1- acb->aiocb.aio_nbytes = nb_sectors *512 ; +if (nb_sectors <0 ) + acb->aiocb.aio_nbytes = -nb_sectors; +else + acb->aiocb.aio_nbytes = nb_sectors *512 ;Ugly hacks like this need at least a decent comment.
Yes, you're right but I'm always wondering if it is the good way to do what I want: read a number of bytes instead of a number of sectors. Perhaps I should define a new function in the qemu AIO interface ?
There is another ugly hack, did you find it ? ;-)
Laurent
Signature · 3 lines
------------- [email protected] -------------- "Any sufficiently advanced technology is indistinguishable from magic." - Arthur C. Clarke
Re: [Qemu-devel] [PATCH 2/2] Real SCSI device passthrough (v3)
Quoted 10 lines · Laurent Vivier
Quoted 8 lines · Paul Brook
Quoted 6 lines · Laurent Vivier
block-raw.c +4
-1- acb->aiocb.aio_nbytes = nb_sectors *512 ; +if (nb_sectors <0 ) + acb->aiocb.aio_nbytes = -nb_sectors; +else + acb->aiocb.aio_nbytes = nb_sectors *512 ;
Quoted 7 lines
Quoted 2 lines
Ugly hacks like this need at least a decent comment.
Yes, you're right but I'm always wondering if it is the good way to do what I want: read a number of bytes instead of a number of sectors. Perhaps I should define a new function in the qemu AIO interface ?
I think the crux of the problem is that you're using the BlockDriver API for something that isn't actually a block driver.
Regards,
Anthony Liguori
Quoted 4 lines
There is another ugly hack, did you find it ? ;-)
Laurent
Re: [Qemu-devel] [PATCH 2/2] Real SCSI device passthrough (v3)
Quoted 14 lines · Anthony Liguori
Quoted 13 lines · Laurent Vivier
Quoted 10 lines · Paul Brook
block-raw.c static RawAIOCB *raw_aio_setup(BlockDriv · line 394
Quoted 6 lines · Laurent Vivier
block-raw.c +4
-1- acb->aiocb.aio_nbytes = nb_sectors *512 ; +if (nb_sectors <0 ) + acb->aiocb.aio_nbytes = -nb_sectors; +else + acb->aiocb.aio_nbytes = nb_sectors *512 ;Ugly hacks like this need at least a decent comment.
Quoted 7 lines
Quoted 4 lines
Yes, you're right but I'm always wondering if it is the good way to do what I want: read a number of bytes instead of a number of sectors. Perhaps I should define a new function in the qemu AIO interface ?
I think the crux of the problem is that you're using the BlockDriver API for something that isn't actually a block driver.
Yes, I know, but I don't want to rewrite all block-raw.c just to change the granularity of the I/O access. It is the best solution I found, if you have some better ideas (and I know you have lot of good ideas), I take them.
Regards,
Laurent
Signature · 3 lines
------------- [email protected] -------------- "Any sufficiently advanced technology is indistinguishable from magic." - Arthur C. Clarke
Quoted 7 lines · Laurent Vivier
This series of patches allows to connect real SCSI device to the virtual SCSI controller of Qemu using the SCSI Generic interface (
/dev/sg)for instance:
qemu -hda my_disk.qcow2 -drive file=/dev/sg3,if=scsi
Please update also the documentation to mention this example.
Quoted 14 lines
[PATCH 1/2] SCSI cleanup
This patch reworks the interface between SCSI controller and SCSI device.
[PATCH 2/2] Real SCSI device passthrough (v3)
This patch allows to connect the virtual SCSI interface of Qemu to a real SCSI device of the host.
Laurent