06.05.2020 18:14, Eric Blake wrote:
On 5/6/20 4:25 AM, Vladimir Sementsov-Ogievskiy wrote:
Currently this field only set by qed and qcow2.
Well, only after patches 1-6 (prior to then, it was also set in protocol
drivers). I think you might be able to hoist part of this patch earlier in the
series, to make the changes to the protocol drivers easier to review, by
rewording this sentence:
Currently, the only format drivers that set this field are qed and qcow2.
But in fact, all
backing-supporting formats (parallels, qcow, qcow2, qed, vmdk) share
this semantics: on unallocated blocks, if there is no backing file they
s/this/these/
just memset the buffer with zeroes.
So, document this behavior for .supports_backing and drop
.unallocated_blocks_are_zero
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
---
include/block/block.h | 6 ------
include/block/block_int.h | 13 ++++++++++++-
block.c | 15 ---------------
block/io.c | 8 ++++----
block/qcow2.c | 1 -
block/qed.c | 1 -
6 files changed, 16 insertions(+), 28 deletions(-)
diff --git a/include/block/block.h b/include/block/block.h
index 8b62429aa4..db1cb503ec 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -21,11 +21,6 @@ typedef struct BlockDriverInfo {
/* offset at which the VM state can be saved (0 if not possible) */
int64_t vm_state_offset;
bool is_dirty;
- /*
- * True if unallocated blocks read back as zeroes. This is equivalent
- * to the LBPRZ flag in the SCSI logical block provisioning page.
- */
- bool unallocated_blocks_are_zero;
You can't delete this field until all protocol drivers are cleaned up, so
deferring this part of the change to the end of the series makes sense.
/*
* True if this block driver only supports compressed writes
*/
@@ -431,7 +426,6 @@ int bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
int64_t bytes);
int bdrv_has_zero_init_1(BlockDriverState *bs);
int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_has_zero_init_truncate(BlockDriverState *bs);
-bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
Doing this cleanup makes sense: there is only one caller of this function
pre-patch, and 0 callers post-patch - but whether the cleanup should be at the
same time as you fix the one caller, or deferred to when you also clean up the
field, is less important.
If I were writing the series:
1 - fix qemu-img.c to not use the field
2 - fix block_status to not use the function
3-n - fix protocol drivers that set the field to also return _ZERO
during block status (but not delete the field at that time)
n+1 - delete unused function and field (from ALL drivers)
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
int64_t bytes, int64_t *pnum, int64_t *map,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 92335f33c7..c156b22c6b 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -115,7 +115,18 @@ struct BlockDriver {
*/
bool bdrv_needs_filename;
- /* Set if a driver can support backing files */
+ /*
+ * Set if a driver can support backing files. This also implies the
+ * following semantics:
+ *
+ * - Return status 0 of .bdrv_co_block_status means that corresponding
+ * blocks are not allocated in this layer of backing-chain
+ * - For such (unallocated) blocks, read will:
+ * - read from backing file if there is one and big enough
s/and/and it is/
+ * - fill buffer with zeroes if there is no backing file
+ * - space after EOF of the backing file considered as zero
+ * (corresponding part of read-buffer must be zeroed by driver)
Does the driver actually have to do the zeroing? Looking at qcow2.c, I see:
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
...
case QCOW2_CLUSTER_UNALLOCATED:
assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
return bdrv_co_preadv_part(bs->backing, offset, bytes,
qiov, qiov_offset, 0);
which just defers to the block layer to handle read-beyond-EOF, rather than an
explicit memset in the driver.
Hmm, yes.
So maybe you can simplify to:
- For such (unallocated) blocks, read will:
- fill buffer with zeros if there is no backing file
- read from the backing file otherwise, where the block layer
takes care of reading zeros beyond EOF if backing file is short
OK
But the effect is the same.
+++ b/block/io.c
@@ -2385,16 +2385,16 @@ static int coroutine_fn
bdrv_co_block_status(BlockDriverState *bs,
if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
ret |= BDRV_BLOCK_ALLOCATED;
- } else if (want_zero) {
- if (bdrv_unallocated_blocks_are_zero(bs)) {
- ret |= BDRV_BLOCK_ZERO;
- } else if (bs->backing) {
+ } else if (want_zero && bs->drv->supports_backing) {
+ if (bs->backing) {
BlockDriverState *bs2 = bs->backing->bs;
int64_t size2 = bdrv_getlength(bs2);
if (size2 >= 0 && offset >= size2) {
ret |= BDRV_BLOCK_ZERO;
}
+ } else {
+ ret |= BDRV_BLOCK_ZERO;
}
I like this part of the change. But if it is done first in the series, it
_does_ have a semantic impact on protocol drivers (previously, protocol drivers
that return 0 but set the field .unallocated_blocks_are_zero will be changed to
report _ZERO; after this patch, protocol drivers do not do that, because they
don't support backing files, and it is now only backing files that do the _ZERO
magic). So doing _just_ this change, along with a better analysis of how it
changes the semantics of 'qemu-io -c map' on protocol drivers while mentioning
why that is okay, would make a better start to the series, rather than here at
the end. Of course, if you defer it to the end, then none of the protocol
drivers set .unallocated_blocks_are_zero anyway, but that cost more review work
on each altered protocol driver.
I understand the idea.. Ha, it looks like an optimization issue :) I use greedy
algorithm, trying to make each patch to be a simple small step to the result.
But greedy algorithm now always optimal as we know. Actually, here, making
first step larger and more complicated, we achieve less total
review-complexity. Good new experience for me, thanks, I'll try the proposed
way.
--
Best regards,
Vladimir