This helper is mandatory to be called before bdrv_co_flush(). In the
other case bdrv_co_flush() will be noop. This helper should be called
after actual write is completed for subsequent flush to perform some
work.
Actually this change is important, without it BDRV_REQ_FUA semantics is
broken completely. flush() is not called. This smells like potential
data loss if somebody relies on BDRV_REQ_FUA.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Hanna Reitz <hreitz@redhat.com>
---
block/io.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/block/io.c b/block/io.c
index f39ff862c11..820b41fab12 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1163,8 +1163,11 @@ bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov, flags);
emulate_flags:
- if (ret == 0 && emulate_fua) {
- ret = bdrv_co_flush(bs);
+ if (ret == 0) {
+ bdrv_advance_flush_gen(bs);
+ if (emulate_fua) {
+ ret = bdrv_co_flush(bs);
+ }
}
if (qiov == &local_qiov) {
@@ -2077,8 +2080,11 @@ bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
}
fail:
- if (ret == 0 && need_flush) {
- ret = bdrv_co_flush(bs);
+ if (ret == 0) {
+ bdrv_advance_flush_gen(bs);
+ if (need_flush) {
+ ret = bdrv_co_flush(bs);
+ }
}
qemu_vfree(buf);
return ret;
@@ -2147,8 +2153,6 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
bdrv_check_request(offset, bytes, &error_abort);
- bdrv_advance_flush_gen(bs);
-
/*
* Discard cannot extend the image, but in error handling cases, such as
* when reverting a qcow2 cluster allocation, the discarded range can pass
@@ -3720,6 +3724,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
}
ret = 0;
out:
+ bdrv_advance_flush_gen(bs);
bdrv_co_write_req_finish(child, req.offset, req.bytes, &req, ret);
tracked_request_end(&req);
bdrv_dec_in_flight(bs);
@@ -3994,6 +4000,7 @@ static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
bytes,
read_flags, write_flags);
}
+ bdrv_advance_flush_gen(dst->bs);
bdrv_co_write_req_finish(dst, dst_offset, bytes, &req, ret);
tracked_request_end(&req);
bdrv_dec_in_flight(dst->bs);
@@ -4187,6 +4194,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
} else {
offset = bs->total_sectors * BDRV_SECTOR_SIZE;
}
+ bdrv_advance_flush_gen(bs);
/*
* It's possible that truncation succeeded but bdrv_refresh_total_sectors
* failed, but the latter doesn't affect how we should finish the request.
--
2.43.5