Commit 3b69e4b9ad3483bafcc3adc948703dc78e84ed33

Authored by aliguori
1 parent 44e3ee8a

Vectored block device API (Avi Kivity)

Most devices that are capable of DMA are also capable of scatter-gather.
With the memory mapping API, this means that the device code needs to be
able to access discontiguous host memory regions.

For block devices, this translates to vectored I/O.  This patch implements
an aynchronous vectored interface for the qemu block devices.  At the moment
all I/O is bounced and submitted through the non-vectored API; in the future
we will convert block devices to natively support vectored I/O wherever
possible.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6397 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 76 additions and 0 deletions
... ... @@ -1246,6 +1246,69 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
1246 1246 /**************************************************************/
1247 1247 /* async I/Os */
1248 1248  
  1249 +typedef struct VectorTranslationState {
  1250 + QEMUIOVector *iov;
  1251 + uint8_t *bounce;
  1252 + int is_write;
  1253 + BlockDriverAIOCB *aiocb;
  1254 + BlockDriverAIOCB *this_aiocb;
  1255 +} VectorTranslationState;
  1256 +
  1257 +static void bdrv_aio_rw_vector_cb(void *opaque, int ret)
  1258 +{
  1259 + VectorTranslationState *s = opaque;
  1260 +
  1261 + if (!s->is_write) {
  1262 + qemu_iovec_from_buffer(s->iov, s->bounce);
  1263 + }
  1264 + qemu_free(s->bounce);
  1265 + s->this_aiocb->cb(s->this_aiocb->opaque, ret);
  1266 + qemu_aio_release(s->this_aiocb);
  1267 +}
  1268 +
  1269 +static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
  1270 + int64_t sector_num,
  1271 + QEMUIOVector *iov,
  1272 + int nb_sectors,
  1273 + BlockDriverCompletionFunc *cb,
  1274 + void *opaque,
  1275 + int is_write)
  1276 +
  1277 +{
  1278 + VectorTranslationState *s = qemu_mallocz(sizeof(*s));
  1279 + BlockDriverAIOCB *aiocb = qemu_aio_get(bs, cb, opaque);
  1280 +
  1281 + s->this_aiocb = aiocb;
  1282 + s->iov = iov;
  1283 + s->bounce = qemu_memalign(512, nb_sectors * 512);
  1284 + s->is_write = is_write;
  1285 + if (is_write) {
  1286 + qemu_iovec_to_buffer(s->iov, s->bounce);
  1287 + s->aiocb = bdrv_aio_write(bs, sector_num, s->bounce, nb_sectors,
  1288 + bdrv_aio_rw_vector_cb, s);
  1289 + } else {
  1290 + s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors,
  1291 + bdrv_aio_rw_vector_cb, s);
  1292 + }
  1293 + return aiocb;
  1294 +}
  1295 +
  1296 +BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
  1297 + QEMUIOVector *iov, int nb_sectors,
  1298 + BlockDriverCompletionFunc *cb, void *opaque)
  1299 +{
  1300 + return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
  1301 + cb, opaque, 0);
  1302 +}
  1303 +
  1304 +BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
  1305 + QEMUIOVector *iov, int nb_sectors,
  1306 + BlockDriverCompletionFunc *cb, void *opaque)
  1307 +{
  1308 + return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
  1309 + cb, opaque, 1);
  1310 +}
  1311 +
1249 1312 BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
1250 1313 uint8_t *buf, int nb_sectors,
1251 1314 BlockDriverCompletionFunc *cb, void *opaque)
... ... @@ -1294,6 +1357,11 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
1294 1357 {
1295 1358 BlockDriver *drv = acb->bs->drv;
1296 1359  
  1360 + if (acb->cb == bdrv_aio_rw_vector_cb) {
  1361 + VectorTranslationState *s = acb->opaque;
  1362 + acb = s->aiocb;
  1363 + }
  1364 +
1297 1365 drv->bdrv_aio_cancel(acb);
1298 1366 }
1299 1367  
... ...
... ... @@ -2,6 +2,7 @@
2 2 #define BLOCK_H
3 3  
4 4 #include "qemu-aio.h"
  5 +#include "qemu-common.h"
5 6  
6 7 /* block.c */
7 8 typedef struct BlockDriver BlockDriver;
... ... @@ -85,6 +86,13 @@ int bdrv_commit(BlockDriverState *bs);
85 86 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
86 87 typedef void BlockDriverCompletionFunc(void *opaque, int ret);
87 88  
  89 +BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
  90 + QEMUIOVector *iov, int nb_sectors,
  91 + BlockDriverCompletionFunc *cb, void *opaque);
  92 +BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
  93 + QEMUIOVector *iov, int nb_sectors,
  94 + BlockDriverCompletionFunc *cb, void *opaque);
  95 +
88 96 BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
89 97 uint8_t *buf, int nb_sectors,
90 98 BlockDriverCompletionFunc *cb, void *opaque);
... ...