diff mbox series

[06/17] block: Improve bdrv_has_zero_init_truncate with backing file

Message ID 20200131174436.2961874-7-eblake@redhat.com (mailing list archive)
State New, archived
Headers show
Series Improve qcow2 all-zero detection | expand

Commit Message

Eric Blake Jan. 31, 2020, 5:44 p.m. UTC
When we added bdrv_has_zero_init_truncate(), we chose to blindly
return 0 if a backing file was present, because we knew of the corner
case where a backing layer larger than the current layer might leak
the tail of the backing layer into the resized region.  But as this
setup is rare, it penalizes the more common case of a backing layer
smaller than the current layer.

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 block.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

Comments

Alberto Garcia Feb. 10, 2020, 6:13 p.m. UTC | #1
On Fri 31 Jan 2020 06:44:25 PM CET, Eric Blake wrote:
> When we added bdrv_has_zero_init_truncate(), we chose to blindly
> return 0 if a backing file was present, because we knew of the corner
> case where a backing layer larger than the current layer might leak
> the tail of the backing layer into the resized region.  But as this
> setup is rare, it penalizes the more common case of a backing layer
> smaller than the current layer.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto
diff mbox series

Patch

diff --git a/block.c b/block.c
index 296845040e59..d132662f3103 100644
--- a/block.c
+++ b/block.c
@@ -5112,9 +5112,19 @@  int bdrv_has_zero_init_truncate(BlockDriverState *bs)
         return 0;
     }

+    /*
+     * If the current layer is smaller than the backing layer,
+     * truncation may expose backing data; treat failure to query size
+     * in the same manner. Otherwise, we can trust the driver.
+     */
+
     if (bs->backing) {
-        /* Depends on the backing image length, but better safe than sorry */
-        return 0;
+        int64_t back = bdrv_getlength(bs->backing->bs);
+        int64_t curr = bdrv_getlength(bs);
+
+        if (back < 0 || curr < back) {
+            return 0;
+        }
     }
     if (bs->drv->bdrv_has_zero_init_truncate) {
         return bs->drv->bdrv_has_zero_init_truncate(bs);