aboutsummaryrefslogtreecommitdiff
path: root/block/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/io.c')
-rw-r--r--block/io.c75
1 files changed, 42 insertions, 33 deletions
diff --git a/block/io.c b/block/io.c
index bd9a19a9c4..ca96b487eb 100644
--- a/block/io.c
+++ b/block/io.c
@@ -92,7 +92,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 ? 1 : 512;
+ bs->bl.request_alignment = (drv->bdrv_co_preadv ||
+ drv->bdrv_aio_preadv) ? 1 : 512;
/* Take some limits from the children as a default */
if (bs->file) {
@@ -924,23 +925,14 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
}
- sector_num = offset >> BDRV_SECTOR_BITS;
- nb_sectors = bytes >> BDRV_SECTOR_BITS;
-
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
- assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
-
- if (drv->bdrv_co_readv) {
- return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
- } else {
+ if (drv->bdrv_aio_preadv) {
BlockAIOCB *acb;
CoroutineIOCompletion co = {
.coroutine = qemu_coroutine_self(),
};
- acb = bs->drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
- bdrv_co_io_em_complete, &co);
+ acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
+ bdrv_co_io_em_complete, &co);
if (acb == NULL) {
return -EIO;
} else {
@@ -948,6 +940,16 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
return co.ret;
}
}
+
+ sector_num = offset >> BDRV_SECTOR_BITS;
+ nb_sectors = bytes >> BDRV_SECTOR_BITS;
+
+ assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
+ assert(drv->bdrv_co_readv);
+
+ return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
}
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
@@ -972,36 +974,37 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
goto emulate_flags;
}
- sector_num = offset >> BDRV_SECTOR_BITS;
- nb_sectors = bytes >> BDRV_SECTOR_BITS;
-
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
- assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
-
- if (drv->bdrv_co_writev_flags) {
- ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov,
- flags & bs->supported_write_flags);
- flags &= ~bs->supported_write_flags;
- } else if (drv->bdrv_co_writev) {
- assert(!bs->supported_write_flags);
- ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
- } else {
+ if (drv->bdrv_aio_pwritev) {
BlockAIOCB *acb;
CoroutineIOCompletion co = {
.coroutine = qemu_coroutine_self(),
};
- acb = bs->drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
- bdrv_co_io_em_complete, &co);
+ acb = drv->bdrv_aio_pwritev(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;
}
+ sector_num = offset >> BDRV_SECTOR_BITS;
+ nb_sectors = bytes >> BDRV_SECTOR_BITS;
+
+ assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
+
+ assert(drv->bdrv_co_writev);
+ ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov,
+ flags & bs->supported_write_flags);
+ flags &= ~bs->supported_write_flags;
+
emulate_flags:
if (ret == 0 && (flags & BDRV_REQ_FUA)) {
ret = bdrv_co_flush(bs);
@@ -1115,13 +1118,15 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
/* FIXME: Should we (perhaps conditionally) be setting
* BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy
* that still correctly reads as zero? */
- ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, pnum, 0);
+ ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, pnum,
+ BDRV_REQ_WRITE_UNCHANGED);
} else {
/* This does not change the data on the disk, it is not
* necessary to flush even in cache=writethrough mode.
*/
ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
- &local_qiov, 0);
+ &local_qiov,
+ BDRV_REQ_WRITE_UNCHANGED);
}
if (ret < 0) {
@@ -1501,7 +1506,11 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
assert(!waited || !req->serialising);
assert(req->overlap_offset <= offset);
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
- assert(child->perm & BLK_PERM_WRITE);
+ if (flags & BDRV_REQ_WRITE_UNCHANGED) {
+ assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
+ } else {
+ assert(child->perm & BLK_PERM_WRITE);
+ }
assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);