From: Anthony Liguori <aligu...@us.ibm.com> Signed-off-by: Anthony Liguori <aligu...@us.ibm.com> --- block.c | 32 ++++++++++++++++++++++++++++++++ block.h | 2 ++ block_int.h | 3 +++ 3 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/block.c b/block.c index f731c7a..5e3476c 100644 --- a/block.c +++ b/block.c @@ -2248,6 +2248,38 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, return ret; } +/** + * Attempt to stream an image starting from sector_num. + * + * @sector_num - the first sector to start streaming from + * @cb - block completion callback + * @opaque - data to pass completion callback + * + * Returns NULL if the image format not support streaming, the image is + * read-only, or no image is open. + * + * The intention of this function is for a user to execute it once with a + * sector_num of 0 and then upon receiving a completion callback, to remember + * the number of sectors "streamed", and then to call this function again with + * an offset adjusted by the number of sectors previously streamed. + * + * This allows a user to progressive stream in an image at a pace that makes + * sense. In general, this function tries to do the smallest amount of I/O + * possible to do some useful work. + * + * This function only really makes sense in combination with a block format + * that supports copy on read and has it enabled. If copy on read is not + * enabled, a block format driver may return NULL. + */ +BlockDriverAIOCB *bdrv_aio_stream(BlockDriverState *bs, int64_t sector_num, + BlockDriverCompletionFunc *cb, void *opaque) +{ + if (!bs->drv || bs->read_only || !bs->drv->bdrv_aio_stream) { + return NULL; + } + + return bs->drv->bdrv_aio_stream(bs, sector_num, cb, opaque); +} typedef struct MultiwriteCB { int error; diff --git a/block.h b/block.h index 52e9cad..fad828a 100644 --- a/block.h +++ b/block.h @@ -119,6 +119,8 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, BlockDriverCompletionFunc *cb, void *opaque); BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); +BlockDriverAIOCB *bdrv_aio_stream(BlockDriverState *bs, int64_t sector_num, + BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); typedef struct BlockRequest { diff --git a/block_int.h b/block_int.h index 545ad11..0c125d0 100644 --- a/block_int.h +++ b/block_int.h @@ -73,6 +73,9 @@ struct BlockDriver { BlockDriverCompletionFunc *cb, void *opaque); BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); + BlockDriverAIOCB *(*bdrv_aio_stream)(BlockDriverState *bs, + int64_t sector_num, + BlockDriverCompletionFunc *cb, void *opaque); int (*bdrv_discard)(BlockDriverState *bs, int64_t sector_num, int nb_sectors); -- 1.7.4.4