All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, kwolf@redhat.com, mreitz@redhat.com
Subject: [Qemu-devel] [PATCH v9 01/13] qcow2: Unallocate unmapped zero clusters if no backing file
Date: Mon, 10 Apr 2017 20:17:06 -0500	[thread overview]
Message-ID: <20170411011718.9152-2-eblake@redhat.com> (raw)
In-Reply-To: <20170411011718.9152-1-eblake@redhat.com>

'qemu-img map' already coalesces information about unallocated
clusters (those with status 0) and pure zero clusters (those
with status BDRV_BLOCK_ZERO and no offset).  Furthermore, all
qcow2 images with no backing file already report all unallocated
clusters (in the preallocation sense of clusters with no offset)
as BDRV_BLOCK_ZERO, regardless of whether the QCOW_OFLAG_ZERO was
set in that L2 entry (QCOW_OFLAG_ZERO also implies a return of
BDRV_BLOCK_ALLOCATED, but we intentionally do not expose that bit
to external users), thanks to generic block layer code in
bdrv_co_get_block_status().

So, for an image with no backing file, having bdrv_pwrite_zeroes
mark clusters as unallocated (defer to backing file) rather than
reads-as-zero (regardless of backing file) makes no difference
to normal behavior, but may potentially allow for fewer writes to
the L2 table of a freshly-created image where the L2 table is
initially written to all-zeroes (although I don't actually know
if we skip an L2 update and flush when re-writing the same
contents as already present).

Furthermore, this matches the behavior of discard_single_l2(), in
favoring an unallocated cluster over a zero cluster when full
discard is requested.

Meanwhile, version 2 qcow2 files (compat=0.10) lack support for an
explicit zero cluster.  This minor tweak therefore allows us to turn
write zeroes with unmap into an actual unallocation on those files,
where they used to return -ENOTSUP and cause an allocation due to
the fallback to explicitly written zeroes.

Note that technically, we _could_ write a cluster as unallocated
rather than zero if a backing file exists but the backing file
also reads as zero, but that's more expensive to determine, so
this optimization is limited to qcow2 without a backing file.

Also note that this patch unmaps a compressed cluster when there
is no backing file, even when BDRV_REQ_MAY_UNMAP was not set, but
it is unlikely to have compressed clusters in a fully preallocated
image (the point of compression is to reduce space requirements),
so the side effect of unmapping a cluster in that case is not
deemed to be a problem.

Finally, note that this change can create a subtle difference if a
backing file is later added with 'qemu-img rebase -u'; pre-patch,
a v3 file (compat=1.1) will have a cluster that still reads as 0
(the cluster is not allocated in the sense of preallocation, but
is provided from the layer), while post-patch the cluster will
now defer to the backing file - but it's already an unsupported
action if you are modifying guest-visible data by messing with
backing chains ;)

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v9: new patch
---
 block/qcow2-cluster.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 100398c..12f44b2 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1579,7 +1579,8 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
         /* Update L2 entries */
         qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
         if (old_offset & QCOW_OFLAG_COMPRESSED || flags & BDRV_REQ_MAY_UNMAP) {
-            l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
+            l2_table[l2_index + i] = bs->backing
+                ? cpu_to_be64(QCOW_OFLAG_ZERO) : 0;
             qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
         } else {
             l2_table[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO);
@@ -1598,8 +1599,11 @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors,
     uint64_t nb_clusters;
     int ret;

-    /* The zero flag is only supported by version 3 and newer */
-    if (s->qcow_version < 3) {
+    /* The zero flag is only supported by version 3 and newer; we
+     * require the use of that flag if there is a backing file or if
+     * we are not allowed to unmap.  */
+    if (s->qcow_version < 3 &&
+        (bs->backing || !(flags & BDRV_REQ_MAY_UNMAP))) {
         return -ENOTSUP;
     }

-- 
2.9.3

  reply	other threads:[~2017-04-11  1:17 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-11  1:17 [Qemu-devel] [PATCH for-2.10 v9 00/13] add blkdebug tests Eric Blake
2017-04-11  1:17 ` Eric Blake [this message]
2017-04-12  9:49   ` [Qemu-devel] [PATCH v9 01/13] qcow2: Unallocate unmapped zero clusters if no backing file Kevin Wolf
2017-04-12 13:32     ` Eric Blake
2017-04-21 18:42     ` Eric Blake
2017-05-11 14:56     ` Eric Blake
2017-05-11 15:18       ` Eric Blake
2017-05-12 16:06       ` Max Reitz
2017-05-12 23:00         ` John Snow
2017-05-15 18:35           ` Max Reitz
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 02/13] iotests: Add test 179 to cover write zeroes with unmap Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 03/13] qemu-io: Switch 'alloc' command to byte-based length Eric Blake
2017-04-11  2:37   ` Philippe Mathieu-Daudé
2017-04-11 12:11     ` Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 04/13] qemu-io: Switch 'map' output to byte-based reporting Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 05/13] qcow2: Optimize write zero of unaligned tail cluster Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 06/13] qcow2: Assert that cluster operations are aligned Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 07/13] qcow2: Discard/zero clusters by byte count Eric Blake
2017-04-11 22:12   ` Eric Blake
2017-04-11 22:15   ` [Qemu-devel] [PATCH v9.5 07/13] fixup! " Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 08/13] blkdebug: Sanity check block layer guarantees Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 09/13] blkdebug: Refactor error injection Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 10/13] blkdebug: Add pass-through write_zero and discard support Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 11/13] blkdebug: Simplify override logic Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 12/13] blkdebug: Add ability to override unmap geometries Eric Blake
2017-04-11  1:17 ` [Qemu-devel] [PATCH v9 13/13] tests: Add coverage for recent block geometry fixes Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170411011718.9152-2-eblake@redhat.com \
    --to=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.