Skip to contentSkip to conversation

SCSI passthrough cleanup

PATCH In review Laurent Vivier 2 participants 8 messages Jan 23, 2008 – Jan 24, 2008 Kbuild

lore
Share & tools
lore
#0 lore raw

cover SCSI passthrough cleanup

This series of patches makes some cleanups in SCSI passthrough and add functionnalities.

[PATCH 1/5] reverse scsi-generic

Reverse previous implementation and restore block-raw-posix.c.

[PATCH 2/5] Move AIO

This patche moves raw AIO part from block-raw-posix.c to qemu-aio-raw.c.

[PATCH 3/5] Add block SG interface

This patch re-implement scsi-generic.c using a new block interface.

[PATCH 4/5] DVD movie support

This patch allows to read a protected/encrypted movie from a DVD.

[PATCH 5/5] SCSI device DMA split

This patch allows to split a READ or WRITE into several READ or WRITE.

Laurent

#5 lore raw

PATCH 5/5 SCSI device DMA split

In reply to Laurent Vivier

With some emulated SCSI devices, like usb-storage or ide-scsi, DMA transfers are limited to 64 kiB or 32 kiB.
This patch allows to split a READ or WRITE into several READ or WRITE.

Laurent

---
 block-sg.c        |    1 
 hw/scsi-generic.c |  110 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 105 insertions(+), 6 deletions(-)
hw/scsi-generic.c +105 -5
Index: qemu/hw/scsi-generic.c
===================================================================
@@ -60,6 +60,8 @@ do { fprintf(stderr, "scsi-generic: " fm
 #define MAX_UINT ((unsigned int)-1)
 #endif
 
+#define MAX_CHUNK 65536
+
 typedef struct SCSIRequest {
     SGRequest sg;
     struct SCSIRequest *next;
@@ -70,6 +72,8 @@ typedef struct SCSIRequest {
     uint8_t *buf;
     int buflen;
     int len;
+    int remaining;
+    int offset;
 } SCSIRequest;
 
 struct SCSIDeviceState
@@ -81,6 +85,7 @@ struct SCSIDeviceState
     void *card;
     int driver_status;
     uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
+    int max_chunk;
 };
 
 /* Global pool of SCSIRequest structures.  */
@@ -98,6 +103,7 @@ static SCSIRequest *scsi_new_request(SCS
         r->buf = NULL;
         r->buflen = 0;
     }
+    r->offset = 0;
     r->dev = s;
     r->tag = tag;
     memset(r->cmd, 0, sizeof(r->cmd));
@@ -186,23 +192,93 @@ static void scsi_cancel_io(SCSIDevice *d
     }
 }
 
+static void scsi_cmd_next(uint8_t *cmd, uint32_t inc)
+{
+    uint32_t addr;
+    switch (cmd[0] >> 5) {
+    case 0:
+        addr = cmd[3] | (cmd[2] << 8);
+        addr += inc;
+        cmd[2] = addr >> 8;
+        cmd[3] = addr;
+        break;
+    case 1:
+    case 2:
+    case 4:
+    case 5:
+        addr = cmd[5] | ((cmd[4] << 8) | ((cmd[3] << 16) | (cmd[2] << 24)));
+        addr += inc;
+        cmd[2] = addr >> 24;
+        cmd[3] = addr >> 16;
+        cmd[4] = addr >> 8;
+        cmd[5] = addr;
+        break;
+    }
+}
+static void scsi_set_length(uint8_t *cmd, uint32_t len)
+{
+    switch (cmd[0] >> 5) {
+    case 0:
+        cmd[4] = len;
+        break;
+    case 1:
+    case 2:
+        cmd[7] = (len >> 8);
+        cmd[8] = len;
+        break;
+    case 4:
+        cmd[10] = len >> 24;
+        cmd[11] = len >> 16;
+        cmd[12] = len >> 8;
+        cmd[13] = len;
+        break;
+    case 5:
+        cmd[6] = len >> 24;
+        cmd[7] = len >> 16;
+        cmd[8] = len >> 8;
+        cmd[9] = len;
+        break;
+    }
+}
+
+
 static int execute_command(BlockDriverState *bdrv,
                            SCSIRequest *r, int direction,
                            BlockDriverCompletionFunc *complete)
 {
+    int ret;
+    SCSIDeviceState *s = r->dev;
+
+    r->remaining = 0;
+retry:
+    if (s->max_chunk && r->buflen > s->max_chunk) {
+        r->remaining = r->buflen - s->max_chunk;
+        scsi_set_length(r->cmd, s->max_chunk / s->blocksize);
+        r->buflen = s->max_chunk;
+    }
     memset(&r->sg, 0, sizeof(r->sg));
     r->sg.io_header.interface_id = 'S';
+    r->sg.io_header.dxferp = r->buf + r->offset;
     r->sg.io_header.dxfer_direction = direction;
     r->sg.io_header.cmd_len = r->cmdlen;
-    r->sg.io_header.mx_sb_len = sizeof(r->dev->sensebuf);
     r->sg.io_header.dxfer_len = r->buflen;
-    r->sg.io_header.dxferp = r->buf;
+    r->sg.io_header.mx_sb_len = sizeof(s->sensebuf);
+    r->sg.io_header.sbp = s->sensebuf;
     r->sg.io_header.cmdp = r->cmd;
-    r->sg.io_header.sbp = r->dev->sensebuf;
     r->sg.io_header.timeout = MAX_UINT;
     r->sg.io_header.flags |= SG_FLAG_DIRECT_IO;
 
-    return bdrv_execute(bdrv, &r->sg, complete);
+    ret = bdrv_execute(bdrv, &r->sg, complete);
+    if (ret == -1 && errno == 12) {
+        if (!s->max_chunk) {
+            s->max_chunk = MAX_CHUNK;
+            goto retry;
+        } else if (s->max_chunk > s->blocksize) {
+            s->max_chunk >>= 1;
+            goto retry;
+        }
+    }
+    return ret;
 }
 
 static void scsi_read_complete(void *request, int ret)
@@ -216,7 +292,18 @@ static void scsi_read_complete(void *req
         scsi_command_complete(r, ret);
         return;
     }
-    len = r->sg.io_header.dxfer_len - r->sg.io_header.resid;
+    r->offset += r->sg.io_header.dxfer_len - r->sg.io_header.resid;
+    if (r->remaining != 0) {
+        scsi_cmd_next(r->cmd, r->buflen / s->blocksize);
+        scsi_set_length(r->cmd, r->remaining / s->blocksize);
+        r->buflen = r->remaining;
+        ret = execute_command(s->bdrv, r, SG_DXFER_FROM_DEV,
+                              scsi_read_complete);
+        if (ret == -1)
+            scsi_command_complete(r, -EINVAL);
+        return;
+    }
+    len = r->offset;
     DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
 
     r->len = -1;
@@ -263,12 +350,24 @@ static void scsi_read_data(SCSIDevice *d
 static void scsi_write_complete(void* request, int ret)
 {
     SCSIRequest* r = (SCSIRequest*)request;
+    SCSIDeviceState *s = r->dev;
     DPRINTF("scsi_write_complete() ret = %d\n", ret);
     if (ret) {
         DPRINTF("IO error\n");
         scsi_command_complete(r, ret);
         return;
     }
+    r->offset += r->sg.io_header.dxfer_len - r->sg.io_header.resid;
+    if (r->remaining != 0) {
+        scsi_cmd_next(r->cmd, r->buflen / s->blocksize);
+        scsi_set_length(r->cmd, r->remaining / s->blocksize);
+        r->buflen = r->remaining;
+        ret = execute_command(s->bdrv, r, SG_DXFER_TO_DEV,
+                              scsi_write_complete);
+        if (ret == -1)
+            scsi_command_complete(r, -EINVAL);
+        return;
+    }
 
     scsi_command_complete(r, ret);
 }
@@ -591,6 +690,7 @@ SCSIDevice *scsi_generic_init(BlockDrive
     s->card = card;
     s->blocksize = get_blocksize(s->bdrv);
     s->driver_status = 0;
+    s->max_chunk = 0;
     memset(s->sensebuf, 0, sizeof(s->sensebuf));
     /* removable media returns 0 if not present */
     if (s->blocksize <= 0)
block-sg.c +0 -1
Index: qemu/block-sg.c
===================================================================
@@ -151,7 +151,6 @@ int sg_execute(BlockDriverState *bs, voi
 
     if (sg_write(bs, (const uint8_t *)&r->io_header,
                  sizeof(r->io_header)) == -1) {
-        BADF("execute_command: write failed ! (%d)\n", errno);
         return -1;
     }
     if (complete == NULL) {
#3 lore raw

PATCH 3/5 Add block SG interface

In reply to Laurent Vivier

This patch re-implement scsi-generic.c using a new block interface called block-sg.c instead of block-raw-posix.c.
It adds a new interface (bdrv_execute) allowing to send command to the device.

Laurent

---
 Makefile          |    2 
 Makefile.target   |    2 
 block-sg.c        |  194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 block-sg.h        |   18 +++++
 block.c           |   21 +++++
 block.h           |    4 +
 block_int.h       |    4 +
 hw/scsi-generic.c |  176 +++++++++++++++++-------------------------------
 8 files changed, 303 insertions(+), 118 deletions(-)
block.c +19 -2
Index: qemu/block.c
===================================================================
@@ -126,13 +126,14 @@ void path_combine(char *dest, int dest_s
 
 static void bdrv_register(BlockDriver *bdrv)
 {
-    if (!bdrv->bdrv_aio_read) {
+    if (!bdrv->bdrv_aio_read && !bdrv->bdrv_execute) {
         /* add AIO emulation layer */
         bdrv->bdrv_aio_read = bdrv_aio_read_em;
         bdrv->bdrv_aio_write = bdrv_aio_write_em;
         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
         bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
-    } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
+    } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread &&
+               !bdrv->bdrv_execute) {
         /* add synchronous IO emulation layer */
         bdrv->bdrv_read = bdrv_read_em;
         bdrv->bdrv_write = bdrv_write_em;
@@ -267,6 +268,8 @@ static BlockDriver *find_image_format(co
         struct stat st;
         if (stat(filename, &st) >= 0 &&
             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
+            if ((st.st_rdev >> 8) == 0x15) /* SG device */
+                return &bdrv_sg_device;
             return &bdrv_host_device;
         }
     }
@@ -1289,6 +1292,7 @@ void bdrv_init(void)
     bdrv_register(&bdrv_vvfat);
     bdrv_register(&bdrv_qcow2);
     bdrv_register(&bdrv_parallels);
+    bdrv_register(&bdrv_sg_device);
 }
 
 void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
@@ -1394,3 +1398,16 @@ void bdrv_set_locked(BlockDriverState *b
         drv->bdrv_set_locked(bs, locked);
     }
 }
+
+/* send a command to a device, needed for generic scsi interface */
+
+int bdrv_execute(BlockDriverState *bs, void *request,
+                 BlockDriverCompletionFunc *complete)
+{
+   BlockDriver *drv = bs->drv;
+
+    if (drv && drv->bdrv_execute) {
+        return drv->bdrv_execute(bs, request, complete);
+    }
+    return -ENOTSUP;
+}
block.h +4 -0
Index: qemu/block.h
===================================================================
@@ -16,6 +16,7 @@ extern BlockDriver bdrv_vpc;
 extern BlockDriver bdrv_vvfat;
 extern BlockDriver bdrv_qcow2;
 extern BlockDriver bdrv_parallels;
+extern BlockDriver bdrv_sg_device;
 
 typedef struct BlockDriverInfo {
     /* in bytes, 0 if irrelevant */
@@ -148,6 +149,9 @@ int bdrv_snapshot_delete(BlockDriverStat
 int bdrv_snapshot_list(BlockDriverState *bs,
                        QEMUSnapshotInfo **psn_info);
 char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
+int bdrv_execute(BlockDriverState *bs, void *request,
+                 BlockDriverCompletionFunc *complete);
+
 
 char *get_human_readable_size(char *buf, int buf_size, int64_t size);
 int path_is_absolute(const char *path);
block-sg.c new file +194 -0

194 lines not on this page · raw message

hw/scsi-generic.c +62 -114

360 lines not on this page · raw message

Makefile.target +1 -1
Index: qemu/Makefile.target
===================================================================
@@ -398,7 +398,7 @@ VL_OBJS=vl.o osdep.o monitor.o pci.o loa
 ifdef CONFIG_WIN32
 VL_OBJS+=block-raw-win32.o
 else
-VL_OBJS+=block-raw-posix.o qemu-aio-posix.o
+VL_OBJS+=block-raw-posix.o block-sg.o qemu-aio-posix.o
 endif
 
 ifdef CONFIG_ALSA
Makefile +1 -1
Index: qemu/Makefile
===================================================================
@@ -40,7 +40,7 @@ recurse-all: $(patsubst %,subdir-%, $(TA
 BLOCK_OBJS=cutils.o
 BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
 BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
-BLOCK_OBJS+=block-qcow2.o block-parallels.o
+BLOCK_OBJS+=block-qcow2.o block-parallels.o block-sg.o
 
 ######################################################################
 # libqemu_common.a: Target indepedent part of system emulation. The
block-sg.h new file +18 -0
Index: qemu/block-sg.h
===================================================================
@@ -0,0 +1,18 @@
+/*
+ * Generic SCSI Device support
+ *
+ * Copyright (c) 2008 Bull S.A.S.
+ *
+ * Written by Laurent Vivier <[email protected]>
+ *
+ * This code is licenced under the LGPL.
+ *
+ */
+
+#define SG_ERR_DRIVER_TIMEOUT 0x06
+#define SG_ERR_DRIVER_SENSE 0x08
+
+typedef struct SGRequest {
+    sg_io_hdr_t io_header;
+    BlockDriverAIOCB *aiocb;
+} SGRequest;
block_int.h +4 -0
Index: qemu/block_int.h
===================================================================
@@ -82,6 +82,10 @@ struct BlockDriver {
     int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
     int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
 
+    /* SG device */
+    int (*bdrv_execute)(BlockDriverState *bs, void *request,
+                        BlockDriverCompletionFunc *complete);
+
     BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
#4 lore raw

PATCH 4/5 DVD movie support

This patch allows to read a protected/encrypted movie from a DVD. (With a Movie Player having the key to decode it, tested with powerDVD)

Laurent

---
 hw/scsi-generic.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
hw/scsi-generic.c +11 -1
Index: qemu/hw/scsi-generic.c
===================================================================
@@ -46,9 +46,12 @@ do { fprintf(stderr, "scsi-generic: " fm
 #include <scsi/scsi.h>
 #include "block-sg.h"
 
+#define BLANK 0xa1
+#define SEND_KEY 0xa3
+#define REPORT_KEY 0xa4
 #define LOAD_UNLOAD 0xa6
+#define READ_DVD_STRUCTURE 0xad
 #define SET_CD_SPEED 0xbb
-#define BLANK 0xa1
 
 #define SCSI_CMD_BUF_SIZE     16
 #define SCSI_SENSE_BUF_SIZE 32
@@ -398,6 +401,12 @@ static int scsi_length(uint8_t *cmd, int
     case READ_12:
         *len *= blocksize;
         break;
+  case READ_DVD_STRUCTURE:
+  case SEND_KEY:
+  case REPORT_KEY:
+      *len &= 0xffff;
+      break;
+
     }
     return 0;
 }
@@ -435,6 +444,7 @@ static int is_write(int command)
     case MEDIUM_SCAN:
     case SEND_VOLUME_TAG:
     case WRITE_LONG_2:
+    case SEND_KEY:
         return 1;
     }
     return 0;
#1 lore raw

PATCH 1/5 reverse scsi-generic

In reply to Laurent Vivier

This patch removes modifications in block interface introduced by the scsi-generic implementation, and disables scsi-generic support.

Files restored are:

block-raw-posix.c       revision 1.2
block.c                 revision 1.52
block.h                 revision 1.5
block_int.h             revision 1.15

Laurent

---
 block-raw-posix.c |   23 +++--------------------
 block.c           |   16 ----------------
 block.h           |    2 --
 block_int.h       |    4 ----
 hw/scsi-generic.c |    3 ++-
 5 files changed, 5 insertions(+), 43 deletions(-)
block.c +0 -16
Index: qemu/block.c
===================================================================
@@ -786,11 +786,6 @@ int bdrv_is_read_only(BlockDriverState *
     return bs->read_only;
 }
 
-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)
@@ -1399,14 +1394,3 @@ 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 +0 -2
Index: qemu/block.h
===================================================================
@@ -119,7 +119,6 @@ int bdrv_get_type_hint(BlockDriverState 
 int 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_media_changed(BlockDriverState *bs);
 int bdrv_is_locked(BlockDriverState *bs);
@@ -149,7 +148,6 @@ int bdrv_snapshot_delete(BlockDriverStat
 int 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 +0 -4
Index: qemu/block_int.h
===================================================================
@@ -82,9 +82,6 @@ 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, void *buf);
-
     BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
@@ -96,7 +93,6 @@ 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;
block-raw-posix.c +3 -20
Index: qemu/block-raw-posix.c
===================================================================
@@ -151,7 +151,7 @@ static int raw_pread(BlockDriverState *b
     if (ret < 0)
         return ret;
 
-    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+    if (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
@@ -204,7 +204,7 @@ static int raw_pwrite(BlockDriverState *
     if (ret < 0)
         return ret;
 
-    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+    if (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) [%"
@@ -387,10 +387,7 @@ 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;
-    if (nb_sectors < 0)
-        acb->aiocb.aio_nbytes = -nb_sectors;
-    else
-        acb->aiocb.aio_nbytes = nb_sectors * 512;
+    acb->aiocb.aio_nbytes = nb_sectors * 512;
     acb->aiocb.aio_offset = sector_num * 512;
     acb->next = first_aio;
     first_aio = acb;
@@ -682,8 +679,6 @@ 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);
@@ -863,12 +858,6 @@ 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)
@@ -891,10 +880,6 @@ static int raw_set_locked(BlockDriverSta
     return -ENOTSUP;
 }
 
-static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
-{
-    return -ENOTSUP;
-}
 #endif /* !linux */
 
 BlockDriver bdrv_host_device = {
@@ -921,6 +906,4 @@ 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,
 };
hw/scsi-generic.c +2 -1
Index: qemu/hw/scsi-generic.c
===================================================================
@@ -15,7 +15,8 @@
 #include "block.h"
 #include "scsi-disk.h"
 
-#ifndef __linux__
+//#ifndef __linux__
+#if 1
 
 SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
                               scsi_completionfn completion, void *opaque)
#2 lore raw

PATCH 2/5 Move AIO

This patche moves raw AIO part from block-raw-posix.c to qemu-aio-raw.c to be able to use raw AIO from other files.

Laurent

---
 Makefile          |    2 
 Makefile.target   |    2 
 block-raw-posix.c |  205 ++-------------------------------------------
 qemu-aio-posix.c  |  241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-aio-posix.h  |   39 ++++++++
 5 files changed, 293 insertions(+), 196 deletions(-)
Makefile.target +1 -1
Index: qemu/Makefile.target
===================================================================
@@ -398,7 +398,7 @@ VL_OBJS=vl.o osdep.o monitor.o pci.o loa
 ifdef CONFIG_WIN32
 VL_OBJS+=block-raw-win32.o
 else
-VL_OBJS+=block-raw-posix.o
+VL_OBJS+=block-raw-posix.o qemu-aio-posix.o
 endif
 
 ifdef CONFIG_ALSA
block-raw-posix.c +11 -194

246 lines not on this page · raw message

Makefile +1 -1
Index: qemu/Makefile
===================================================================
@@ -136,7 +136,7 @@ QEMU_IMG_BLOCK_OBJS = $(BLOCK_OBJS)
 ifdef CONFIG_WIN32
 QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-win32.o
 else
-QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-posix.o
+QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-posix.o qemu-img-qemu-aio-posix.o
 endif
 
 ######################################################################
qemu-aio-posix.c new file +241 -0

241 lines not on this page · raw message

qemu-aio-posix.h new file +39 -0
Index: qemu/qemu-aio-posix.h
===================================================================
@@ -0,0 +1,39 @@
+/*
+ * QEMU Asynchronous I/O
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <aio.h>
+
+typedef struct RawAIOCB {
+    BlockDriverAIOCB common;
+    struct aiocb aiocb;
+    struct RawAIOCB *next;
+} RawAIOCB;
+
+RawAIOCB *qemu_aio_read(BlockDriverState *bs,
+        int64_t offset, uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque);
+RawAIOCB *qemu_aio_write(BlockDriverState *bs,
+        int64_t offset, const uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque);
+void qemu_aio_cancel(RawAIOCB *acb);
#6 lore raw
In reply to Laurent Vivier

Two questions:

- Why do you use AIO ? If the Linux sg device supports selects, then using the QEMU select() callback suffices.

- Why do you use a block device ?

Regards,

Fabrice.

Quoted 29 lines · Laurent Vivier

This series of patches makes some cleanups in SCSI passthrough and add functionnalities.

[PATCH 1/5] reverse scsi-generic

Reverse previous implementation and restore block-raw-posix.c.

[PATCH 2/5] Move AIO

This patche moves raw AIO part from block-raw-posix.c to qemu-aio-raw.c.

[PATCH 3/5] Add block SG interface

This patch re-implement scsi-generic.c using a new block interface.

[PATCH 4/5] DVD movie support

This patch allows to read a protected/encrypted movie from a DVD.

[PATCH 5/5] SCSI device DMA split

This patch allows to split a READ or WRITE into several READ or WRITE.

Laurent

#7 lore raw
Quoted 4 lines · Fabrice Bellard

Two questions:

- Why do you use AIO ? If the Linux sg device supports selects, then using the QEMU select() callback suffices.

Basically because when I want to have asynchronous I/O I use AIO... If you explain me briefly how to use selects in Qemu I can try.

Quoted 1 line

- Why do you use a block device ?

Because to communicate with SG device we need a file descriptor, and using current mechanism (with -drive) allows to have this file descriptor without modifying anything else (without adding a new parameter). Moreover, to use Qemu AIO I need a BlockDriverState (but it related to the first question...)

I agree to change all of this if you give me tips to use selects in Qemu and if you thing adding a new command line parameter is not an issue.

Quoted 3 lines

Regards,

Fabrice.

Thank you for your comments and help,
Laurent

Quoted 32 lines
Quoted 29 lines · Laurent Vivier

This series of patches makes some cleanups in SCSI passthrough and add functionnalities.

[PATCH 1/5] reverse scsi-generic

Reverse previous implementation and restore block-raw-posix.c.

[PATCH 2/5] Move AIO

This patche moves raw AIO part from block-raw-posix.c to qemu-aio-raw.c.

[PATCH 3/5] Add block SG interface

This patch re-implement scsi-generic.c using a new block interface.

[PATCH 4/5] DVD movie support

This patch allows to read a protected/encrypted movie from a DVD.

[PATCH 5/5] SCSI device DMA split

This patch allows to split a READ or WRITE into several READ or WRITE.

Laurent

Signature · 3 lines
----------------- [email protected]  ------------------
  "La perfection est atteinte non quand il ne reste rien à
ajouter mais quand il ne reste rien à enlever." Saint Exupéry