From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LQ2tt-0003Gw-2N for qemu-devel@nongnu.org; Thu, 22 Jan 2009 11:59:29 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LQ2ts-0003Gc-C2 for qemu-devel@nongnu.org; Thu, 22 Jan 2009 11:59:28 -0500 Received: from [199.232.76.173] (port=53706 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LQ2ts-0003GS-1K for qemu-devel@nongnu.org; Thu, 22 Jan 2009 11:59:28 -0500 Received: from savannah.gnu.org ([199.232.41.3]:37260 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LQ2tr-00042B-3A for qemu-devel@nongnu.org; Thu, 22 Jan 2009 11:59:27 -0500 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1LQ2to-0003LR-SR for qemu-devel@nongnu.org; Thu, 22 Jan 2009 16:59:24 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1LQ2to-0003LM-Kf for qemu-devel@nongnu.org; Thu, 22 Jan 2009 16:59:24 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Thu, 22 Jan 2009 16:59:24 +0000 Subject: [Qemu-devel] [6397] Vectored block device API (Avi Kivity) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 6397 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6397 Author: aliguori Date: 2009-01-22 16:59:24 +0000 (Thu, 22 Jan 2009) Log Message: ----------- 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 Signed-off-by: Anthony Liguori Modified Paths: -------------- trunk/block.c trunk/block.h Modified: trunk/block.c =================================================================== --- trunk/block.c 2009-01-22 16:59:20 UTC (rev 6396) +++ trunk/block.c 2009-01-22 16:59:24 UTC (rev 6397) @@ -1246,6 +1246,69 @@ /**************************************************************/ /* async I/Os */ +typedef struct VectorTranslationState { + QEMUIOVector *iov; + uint8_t *bounce; + int is_write; + BlockDriverAIOCB *aiocb; + BlockDriverAIOCB *this_aiocb; +} VectorTranslationState; + +static void bdrv_aio_rw_vector_cb(void *opaque, int ret) +{ + VectorTranslationState *s = opaque; + + if (!s->is_write) { + qemu_iovec_from_buffer(s->iov, s->bounce); + } + qemu_free(s->bounce); + s->this_aiocb->cb(s->this_aiocb->opaque, ret); + qemu_aio_release(s->this_aiocb); +} + +static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *iov, + int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque, + int is_write) + +{ + VectorTranslationState *s = qemu_mallocz(sizeof(*s)); + BlockDriverAIOCB *aiocb = qemu_aio_get(bs, cb, opaque); + + s->this_aiocb = aiocb; + s->iov = iov; + s->bounce = qemu_memalign(512, nb_sectors * 512); + s->is_write = is_write; + if (is_write) { + qemu_iovec_to_buffer(s->iov, s->bounce); + s->aiocb = bdrv_aio_write(bs, sector_num, s->bounce, nb_sectors, + bdrv_aio_rw_vector_cb, s); + } else { + s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors, + bdrv_aio_rw_vector_cb, s); + } + return aiocb; +} + +BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors, + cb, opaque, 0); +} + +BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors, + cb, opaque, 1); +} + BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) @@ -1294,6 +1357,11 @@ { BlockDriver *drv = acb->bs->drv; + if (acb->cb == bdrv_aio_rw_vector_cb) { + VectorTranslationState *s = acb->opaque; + acb = s->aiocb; + } + drv->bdrv_aio_cancel(acb); } Modified: trunk/block.h =================================================================== --- trunk/block.h 2009-01-22 16:59:20 UTC (rev 6396) +++ trunk/block.h 2009-01-22 16:59:24 UTC (rev 6397) @@ -2,6 +2,7 @@ #define BLOCK_H #include "qemu-aio.h" +#include "qemu-common.h" /* block.c */ typedef struct BlockDriver BlockDriver; @@ -85,6 +86,13 @@ typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); +BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); +BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); + BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque);