scsi-disk: enable scatter/gather functionality

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2011-10-12 15:12:14 +02:00
parent 3d5aba97e9
commit 5d0d246792
2 changed files with 51 additions and 13 deletions

View file

@ -87,6 +87,7 @@ static void scsi_dma_restart_bh(void *opaque)
scsi_req_continue(req); scsi_req_continue(req);
break; break;
case SCSI_XFER_NONE: case SCSI_XFER_NONE:
assert(!req->sg);
scsi_req_dequeue(req); scsi_req_dequeue(req);
scsi_req_enqueue(req); scsi_req_enqueue(req);
break; break;

View file

@ -38,6 +38,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "sysemu.h" #include "sysemu.h"
#include "blockdev.h" #include "blockdev.h"
#include "block_int.h" #include "block_int.h"
#include "dma.h"
#ifdef __linux #ifdef __linux
#include <scsi/sg.h> #include <scsi/sg.h>
@ -123,6 +124,27 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r)
return r->qiov.size / 512; return r->qiov.size / 512;
} }
static void scsi_dma_complete(void *opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
bdrv_acct_done(s->qdev.conf.bs, &r->acct);
if (ret) {
if (scsi_handle_rw_error(r, -ret)) {
goto done;
}
}
r->sector += r->sector_count;
r->sector_count = 0;
scsi_req_complete(&r->req, GOOD);
done:
scsi_req_unref(&r->req);
}
static void scsi_read_complete(void * opaque, int ret) static void scsi_read_complete(void * opaque, int ret)
{ {
SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@ -213,10 +235,17 @@ static void scsi_read_data(SCSIRequest *req)
return; return;
} }
n = scsi_init_iovec(r); if (r->req.sg) {
bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n, r->req.resid -= r->req.sg->size;
scsi_read_complete, r); r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
scsi_dma_complete, r);
} else {
n = scsi_init_iovec(r);
bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
scsi_read_complete, r);
}
} }
/* /*
@ -315,18 +344,26 @@ static void scsi_write_data(SCSIRequest *req)
return; return;
} }
n = r->qiov.size / 512; if (!r->req.sg && !r->qiov.size) {
if (n) { /* Called for the first time. Ask the driver to send us more data. */
if (s->tray_open) { scsi_write_complete(r, 0);
scsi_write_complete(r, -ENOMEDIUM); return;
return; }
} if (s->tray_open) {
scsi_write_complete(r, -ENOMEDIUM);
return;
}
if (r->req.sg) {
dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
r->req.resid -= r->req.sg->size;
r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
scsi_dma_complete, r);
} else {
n = r->qiov.size / 512;
bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE); bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n, r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
scsi_write_complete, r); scsi_write_complete, r);
} else {
/* Called for the first time. Ask the driver to send us more data. */
scsi_write_complete(r, 0);
} }
} }