Commit 221f715d authored by Anthony Liguori's avatar Anthony Liguori
Browse files

new scsi-generic abstraction, use SG_IO (Christoph Hellwig)



Okay, I started looking into how to handle scsi-generic I/O in the
new world order.

I think the best is to use the SG_IO ioctl instead of the read/write
interface as that allows us to support scsi passthrough on disk/cdrom
devices, too.  See Hannes patch on the kvm list from August for an
example.

Now that we always do ioctls we don't need another abstraction than
bdrv_ioctl for the synchronous requests for now, and for asynchronous
requests I've added a aio_ioctl abstraction keeping it simple.

Long-term we might want to move the ops to a higher-level abstraction
and let the low-level code fill out the request header, but I'm lazy
enough to leave that to the people trying to support scsi-passthrough
on a non-Linux OS.

Tested lightly by issuing various sg_ commands from sg3-utils in a guest
to a host CDROM device.


Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6895 c046a42c-6fe2-441c-8c8c-71466251a162
parent 64a7fde8
Loading
Loading
Loading
Loading
+26 −28
Original line number Diff line number Diff line
@@ -1209,6 +1209,26 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)

    return ioctl(s->fd, req, buf);
}

static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
        unsigned long int req, void *buf,
        BlockDriverCompletionFunc *cb, void *opaque)
{
    RawAIOCB *acb;

    acb = raw_aio_setup(bs, 0, buf, 0, cb, opaque);
    if (!acb)
        return NULL;

    acb->aiocb.aio_ioctl_cmd = req;
    if (qemu_paio_ioctl(&acb->aiocb) < 0) {
        raw_aio_remove(acb);
        return NULL;
    }

    return &acb->common;
}

#elif defined(__FreeBSD__)

static int fd_open(BlockDriverState *bs)
@@ -1349,33 +1369,14 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
    return -ENOTSUP;
}
#endif /* !linux && !FreeBSD */

static int raw_sg_send_command(BlockDriverState *bs, void *buf, int count)
{
    return raw_pwrite(bs, -1, buf, count);
}

static int raw_sg_recv_response(BlockDriverState *bs, void *buf, int count)
{
    return raw_pread(bs, -1, buf, count);
}

static BlockDriverAIOCB *raw_sg_aio_read(BlockDriverState *bs,
                                         void *buf, int count,
                                         BlockDriverCompletionFunc *cb,
                                         void *opaque)
{
    return raw_aio_read(bs, 0, buf, -(int64_t)count, cb, opaque);
}

static BlockDriverAIOCB *raw_sg_aio_write(BlockDriverState *bs,
                                          void *buf, int count,
                                          BlockDriverCompletionFunc *cb,
                                          void *opaque)
static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
        unsigned long int req, void *buf,
        BlockDriverCompletionFunc *cb, void *opaque)
{
    return raw_aio_write(bs, 0, buf, -(int64_t)count, cb, opaque);
    return -ENOTSUP;
}
#endif /* !linux && !FreeBSD */

BlockDriver bdrv_host_device = {
    .format_name	= "host_device",
@@ -1402,8 +1403,5 @@ BlockDriver bdrv_host_device = {
    .bdrv_set_locked	= raw_set_locked,
    /* generic scsi device */
    .bdrv_ioctl		= raw_ioctl,
    .bdrv_sg_send_command  = raw_sg_send_command,
    .bdrv_sg_recv_response = raw_sg_recv_response,
    .bdrv_sg_aio_read      = raw_sg_aio_read,
    .bdrv_sg_aio_write     = raw_sg_aio_write,
    .bdrv_aio_ioctl	= raw_aio_ioctl,
};
+7 −18
Original line number Diff line number Diff line
@@ -1633,24 +1633,13 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
    return -ENOTSUP;
}

int bdrv_sg_send_command(BlockDriverState *bs, void *buf, int count)
{
    return bs->drv->bdrv_sg_send_command(bs, buf, count);
}

int bdrv_sg_recv_response(BlockDriverState *bs, void *buf, int count)
{
    return bs->drv->bdrv_sg_recv_response(bs, buf, count);
}

BlockDriverAIOCB *bdrv_sg_aio_read(BlockDriverState *bs, void *buf, int count,
BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
        unsigned long int req, void *buf,
        BlockDriverCompletionFunc *cb, void *opaque)
{
    return bs->drv->bdrv_sg_aio_read(bs, buf, count, cb, opaque);
}
    BlockDriver *drv = bs->drv;

BlockDriverAIOCB *bdrv_sg_aio_write(BlockDriverState *bs, void *buf, int count,
                                    BlockDriverCompletionFunc *cb, void *opaque)
{
    return bs->drv->bdrv_sg_aio_write(bs, buf, count, cb, opaque);
    if (drv && drv->bdrv_aio_ioctl)
        return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
    return NULL;
}
+4 −7
Original line number Diff line number Diff line
@@ -102,11 +102,9 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
void bdrv_aio_cancel(BlockDriverAIOCB *acb);

/* sg packet commands */
int bdrv_sg_send_command(BlockDriverState *bs, void *buf, int count);
int bdrv_sg_recv_response(BlockDriverState *bs, void *buf, int count);
BlockDriverAIOCB *bdrv_sg_aio_read(BlockDriverState *bs, void *buf, int count,
                                   BlockDriverCompletionFunc *cb, void *opaque);
BlockDriverAIOCB *bdrv_sg_aio_write(BlockDriverState *bs, void *buf, int count,
int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
        unsigned long int req, void *buf,
        BlockDriverCompletionFunc *cb, void *opaque);

/* Ensure contents are flushed to disk.  */
@@ -169,7 +167,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
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);
+3 −10
Original line number Diff line number Diff line
@@ -86,16 +86,9 @@ struct BlockDriver {

    /* to control generic scsi devices */
    int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
    int (*bdrv_sg_send_command)(BlockDriverState *bs, void *buf, int count);
    int (*bdrv_sg_recv_response)(BlockDriverState *bs, void *buf, int count);
    BlockDriverAIOCB *(*bdrv_sg_aio_read)(BlockDriverState *bs,
                                          void *buf, int count,
                                          BlockDriverCompletionFunc *cb,
                                          void *opaque);
    BlockDriverAIOCB *(*bdrv_sg_aio_write)(BlockDriverState *bs,
                                           void *buf, int count,
                                           BlockDriverCompletionFunc *cb,
                                           void *opaque);
    BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
        unsigned long int req, void *buf,
        BlockDriverCompletionFunc *cb, void *opaque);

    AIOPool aio_pool;
    struct BlockDriver *next;
+3 −39
Original line number Diff line number Diff line
@@ -201,8 +201,6 @@ static int execute_command(BlockDriverState *bdrv,
                           SCSIRequest *r, int direction,
			   BlockDriverCompletionFunc *complete)
{
    int ret;

    r->io_header.interface_id = 'S';
    r->io_header.dxfer_direction = direction;
    r->io_header.dxferp = r->buf;
@@ -215,27 +213,7 @@ static int execute_command(BlockDriverState *bdrv,
    r->io_header.usr_ptr = r;
    r->io_header.flags |= SG_FLAG_DIRECT_IO;

    ret = bdrv_sg_send_command(bdrv, &r->io_header, sizeof(r->io_header));
    if (ret < 0) {
        BADF("execute_command: write failed ! (%d)\n", errno);
        return -1;
    }
    if (complete == NULL) {
        int ret;
        r->aiocb = NULL;
        while ((ret = bdrv_sg_recv_response(bdrv, &r->io_header,
                                            sizeof(r->io_header))) < 0 &&
               ret == -EINTR)
            ;
        if (ret < 0) {
            BADF("execute_command: read failed !\n");
            return -1;
        }
        return 0;
    }

    r->aiocb = bdrv_sg_aio_read(bdrv, (uint8_t*)&r->io_header,
                                sizeof(r->io_header), complete, r);
    r->aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
    if (r->aiocb == NULL) {
        BADF("execute_command: read failed !\n");
        return -1;
@@ -637,14 +615,7 @@ static int get_blocksize(BlockDriverState *bdrv)
    io_header.sbp = sensebuf;
    io_header.timeout = 6000; /* XXX */

    ret = bdrv_sg_send_command(bdrv, &io_header, sizeof(io_header));
    if (ret < 0)
        return -1;

    while ((ret = bdrv_sg_recv_response(bdrv, &io_header, sizeof(io_header))) < 0 &&
           ret == -EINTR)
        ;

    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
    if (ret < 0)
        return -1;

@@ -675,14 +646,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
    io_header.sbp = sensebuf;
    io_header.timeout = 6000; /* XXX */

    ret = bdrv_sg_send_command(bdrv, &io_header, sizeof(io_header));
    if (ret < 0)
        return -1;

    while ((ret = bdrv_sg_recv_response(bdrv, &io_header, sizeof(io_header))) < 0 &&
           ret == -EINTR)
        ;

    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
    if (ret < 0)
        return -1;

Loading