Some storages(i.e. librbd) already have interfaces to handle some SCSI commands directly. This patch adds COMPARE_AND_WRITE command support through the write path in the block io layer by introducing a new element BDRV_REQ_COMPARE_AND_WRITE into BdrvRequestFlags which indicates a COMPARE_AND_WRITE request. In this way we could easily extend to other SCSI commands support like WRITE_SAME in the future.
Signed-off-by: Yaowei Bai <baiyao...@cmss.chinamobile.com> --- block/io.c | 20 ++++++++++++++++++++ include/block/block.h | 5 +++-- include/block/block_int.h | 3 +++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/block/io.c b/block/io.c index f75777f..3507d71 100644 --- a/block/io.c +++ b/block/io.c @@ -1186,6 +1186,26 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, goto emulate_flags; } + if (drv->bdrv_aio_compare_and_write && + (flags & BDRV_REQ_COMPARE_AND_WRITE)) { + BlockAIOCB *acb; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + acb = drv->bdrv_aio_compare_and_write(bs, offset, bytes, qiov, + flags & bs->supported_write_flags, + bdrv_co_io_em_complete, &co); + flags &= ~bs->supported_write_flags; + if (acb == NULL) { + ret = -EIO; + } else { + qemu_coroutine_yield(); + ret = co.ret; + } + goto emulate_flags; + } + if (drv->bdrv_aio_pwritev) { BlockAIOCB *acb; CoroutineIOCompletion co = { diff --git a/include/block/block.h b/include/block/block.h index 1df9848..f71aa4f 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -92,9 +92,10 @@ typedef enum { * on read request and means that caller doesn't really need data to be * written to qiov parameter which may be NULL. */ - BDRV_REQ_PREFETCH = 0x200, + BDRV_REQ_PREFETCH = 0x200, + BDRV_REQ_COMPARE_AND_WRITE = 0x400, /* Mask of valid flags */ - BDRV_REQ_MASK = 0x3ff, + BDRV_REQ_MASK = 0x7ff, } BdrvRequestFlags; typedef struct BlockSizes { diff --git a/include/block/block_int.h b/include/block/block_int.h index dd033d0..96096e0 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -189,6 +189,9 @@ struct BlockDriver { BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs, int64_t offset, int bytes, BlockCompletionFunc *cb, void *opaque); + BlockAIOCB *(*bdrv_aio_compare_and_write)(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags, + BlockCompletionFunc *cb, void *opaque); int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); -- 1.8.3.1