aboutsummaryrefslogtreecommitdiff
path: root/block/io.c
diff options
context:
space:
mode:
authorVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>2019-06-04 19:15:06 +0300
committerStefan Hajnoczi <stefanha@redhat.com>2019-08-27 14:58:42 +0100
commitac850bf099f8a356788d487c5205345dfd755fca (patch)
tree4a28c7ae9b6ff9c90ad8231885eabc7a42df49f6 /block/io.c
parent7a3f542fbdfd799be4fa6f8b96dc8c1e6933fce4 (diff)
downloadqemu-ac850bf099f8a356788d487c5205345dfd755fca.zip
qemu-ac850bf099f8a356788d487c5205345dfd755fca.tar.gz
qemu-ac850bf099f8a356788d487c5205345dfd755fca.tar.bz2
block: define .*_part io handlers in BlockDriver
Add handlers supporting qiov_offset parameter: bdrv_co_preadv_part bdrv_co_pwritev_part bdrv_co_pwritev_compressed_part This is used to reduce need of defining local_qiovs and hd_qiovs in all corners of block layer code. The following patches will increase usage of this new API part by part. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 20190604161514.262241-5-vsementsov@virtuozzo.com Message-Id: <20190604161514.262241-5-vsementsov@virtuozzo.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/io.c')
-rw-r--r--block/io.c96
1 files changed, 77 insertions, 19 deletions
diff --git a/block/io.c b/block/io.c
index 04e6940..fd2fc7d 100644
--- a/block/io.c
+++ b/block/io.c
@@ -146,7 +146,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
/* Default alignment based on whether driver has byte interface */
bs->bl.request_alignment = (drv->bdrv_co_preadv ||
- drv->bdrv_aio_preadv) ? 1 : 512;
+ drv->bdrv_aio_preadv ||
+ drv->bdrv_co_preadv_part) ? 1 : 512;
/* Take some limits from the children as a default */
if (bs->file) {
@@ -1044,11 +1045,14 @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
uint64_t offset, uint64_t bytes,
- QEMUIOVector *qiov, int flags)
+ QEMUIOVector *qiov,
+ size_t qiov_offset, int flags)
{
BlockDriver *drv = bs->drv;
int64_t sector_num;
unsigned int nb_sectors;
+ QEMUIOVector local_qiov;
+ int ret;
assert(!(flags & ~BDRV_REQ_MASK));
assert(!(flags & BDRV_REQ_NO_FALLBACK));
@@ -1057,8 +1061,19 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
return -ENOMEDIUM;
}
+ if (drv->bdrv_co_preadv_part) {
+ return drv->bdrv_co_preadv_part(bs, offset, bytes, qiov, qiov_offset,
+ flags);
+ }
+
+ if (qiov_offset > 0 || bytes != qiov->size) {
+ qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
+ qiov = &local_qiov;
+ }
+
if (drv->bdrv_co_preadv) {
- return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
+ ret = drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
+ goto out;
}
if (drv->bdrv_aio_preadv) {
@@ -1070,10 +1085,12 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
bdrv_co_io_em_complete, &co);
if (acb == NULL) {
- return -EIO;
+ ret = -EIO;
+ goto out;
} else {
qemu_coroutine_yield();
- return co.ret;
+ ret = co.ret;
+ goto out;
}
}
@@ -1085,16 +1102,25 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
assert(drv->bdrv_co_readv);
- return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+ ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+
+out:
+ if (qiov == &local_qiov) {
+ qemu_iovec_destroy(&local_qiov);
+ }
+
+ return ret;
}
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
uint64_t offset, uint64_t bytes,
- QEMUIOVector *qiov, int flags)
+ QEMUIOVector *qiov,
+ size_t qiov_offset, int flags)
{
BlockDriver *drv = bs->drv;
int64_t sector_num;
unsigned int nb_sectors;
+ QEMUIOVector local_qiov;
int ret;
assert(!(flags & ~BDRV_REQ_MASK));
@@ -1104,6 +1130,18 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
return -ENOMEDIUM;
}
+ if (drv->bdrv_co_pwritev_part) {
+ ret = drv->bdrv_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset,
+ flags & bs->supported_write_flags);
+ flags &= ~bs->supported_write_flags;
+ goto emulate_flags;
+ }
+
+ if (qiov_offset > 0 || bytes != qiov->size) {
+ qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
+ qiov = &local_qiov;
+ }
+
if (drv->bdrv_co_pwritev) {
ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov,
flags & bs->supported_write_flags);
@@ -1147,24 +1185,44 @@ emulate_flags:
ret = bdrv_co_flush(bs);
}
+ if (qiov == &local_qiov) {
+ qemu_iovec_destroy(&local_qiov);
+ }
+
return ret;
}
static int coroutine_fn
bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
- uint64_t bytes, QEMUIOVector *qiov)
+ uint64_t bytes, QEMUIOVector *qiov,
+ size_t qiov_offset)
{
BlockDriver *drv = bs->drv;
+ QEMUIOVector local_qiov;
+ int ret;
if (!drv) {
return -ENOMEDIUM;
}
- if (!drv->bdrv_co_pwritev_compressed) {
+ if (!block_driver_can_compress(drv)) {
return -ENOTSUP;
}
- return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
+ if (drv->bdrv_co_pwritev_compressed_part) {
+ return drv->bdrv_co_pwritev_compressed_part(bs, offset, bytes,
+ qiov, qiov_offset);
+ }
+
+ if (qiov_offset == 0) {
+ return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
+ }
+
+ qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
+ ret = drv->bdrv_co_pwritev_compressed(bs, offset, bytes, &local_qiov);
+ qemu_iovec_destroy(&local_qiov);
+
+ return ret;
}
static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
@@ -1249,7 +1307,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
- &local_qiov, 0);
+ &local_qiov, 0, 0);
if (ret < 0) {
goto err;
}
@@ -1267,7 +1325,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
* necessary to flush even in cache=writethrough mode.
*/
ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
- &local_qiov,
+ &local_qiov, 0,
BDRV_REQ_WRITE_UNCHANGED);
}
@@ -1289,7 +1347,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
qemu_iovec_init(&local_qiov, qiov->niov);
qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes);
ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size,
- &local_qiov, 0);
+ &local_qiov, 0, 0);
qemu_iovec_destroy(&local_qiov);
if (ret < 0) {
goto err;
@@ -1380,7 +1438,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
if (bytes <= max_bytes && bytes <= max_transfer) {
- ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0);
+ ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0, 0);
goto out;
}
@@ -1396,7 +1454,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);
ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining,
- num, &local_qiov, 0);
+ num, &local_qiov, 0, 0);
max_bytes -= num;
qemu_iovec_destroy(&local_qiov);
} else {
@@ -1701,7 +1759,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
}
qemu_iovec_init_buf(&qiov, buf, num);
- ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags);
+ ret = bdrv_driver_pwritev(bs, offset, num, &qiov, 0, write_flags);
/* Keep bounce buffer around if it is big enough for all
* all future requests.
@@ -1857,10 +1915,10 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
- ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov);
+ ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, 0);
} else if (bytes <= max_transfer) {
bdrv_debug_event(bs, BLKDBG_PWRITEV);
- ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
+ ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 0, flags);
} else {
bdrv_debug_event(bs, BLKDBG_PWRITEV);
while (bytes_remaining) {
@@ -1879,7 +1937,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);
ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining,
- num, &local_qiov, local_flags);
+ num, &local_qiov, 0, local_flags);
qemu_iovec_destroy(&local_qiov);
if (ret < 0) {
break;