qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] qcow2: handle discard-no-unref in measure
@ 2024-06-05 13:25 Jean-Louis Dupond
  2024-06-05 13:25 ` [PATCH v2 2/2] qcow2: don't allow discard-no-unref when discard is not enabled Jean-Louis Dupond
  2024-07-10 12:58 ` [PATCH v2 1/2] qcow2: handle discard-no-unref in measure Hanna Czenczek
  0 siblings, 2 replies; 7+ messages in thread
From: Jean-Louis Dupond @ 2024-06-05 13:25 UTC (permalink / raw)
  To: qemu-devel, kwolf, hreitz, andrey.drobyshev; +Cc: Jean-Louis Dupond

When doing a measure on an image with a backing file and
discard-no-unref is enabled, the code should take this into account.

If for example you have a snapshot image with a base, and you do a
discard within the snapshot, it will be ZERO and ALLOCATED, but without
host offset.
Now if we commit this snapshot, and the clusters in the base image have
a host offset, the clusters will only be set to ZERO, but the host offset
will not be cleared.
Therefor non-data clusters in the top image need to check the
base to see if space will be freed or not, to have a correct measure
output.

Bug-Url: https://gitlab.com/qemu-project/qemu/-/issues/2369
Signed-off-by: Jean-Louis Dupond <jean-louis@dupond.be>
---
 block/qcow2.c | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 956128b409..50354e5b98 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5163,9 +5163,16 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
         } else {
             int64_t offset;
             int64_t pnum = 0;
+            BlockDriverState *parent = bdrv_filter_or_cow_bs(in_bs);
+            BDRVQcow2State *s = NULL;
+
+            if (parent) {
+                s = parent->opaque;
+            }
 
             for (offset = 0; offset < ssize; offset += pnum) {
                 int ret;
+                int retp = 0;
 
                 ret = bdrv_block_status_above(in_bs, NULL, offset,
                                               ssize - offset, &pnum, NULL,
@@ -5176,10 +5183,29 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
                     goto err;
                 }
 
-                if (ret & BDRV_BLOCK_ZERO) {
+                /* If we have a parent in the chain and the current block is not data,
+                 * then we want to check the allocation state of the parent block.
+                 * If it has a valid offset, then we want to include it into
+                 * the calculation, cause blocks with an offset will not be freed when
+                 * committing the top into base with discard-no-unref enabled.
+                 */
+                if (parent && s->discard_no_unref && !(ret & BDRV_BLOCK_DATA)) {
+                        int64_t pnum_parent = 0;
+                        retp = bdrv_block_status_above(parent, NULL, offset,
+                                              ssize - offset, &pnum_parent, NULL,
+                                              NULL);
+                        /* If the parent continuous block is smaller, use that pnum,
+                         * so the next iteration starts with the smallest offset.
+                         */
+                        if (pnum_parent < pnum) {
+                            pnum = pnum_parent;
+                        }
+                }
+                if (ret & BDRV_BLOCK_ZERO && !parent && !(parent && s->discard_no_unref)) {
                     /* Skip zero regions (safe with no backing file) */
-                } else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ==
-                           (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) {
+                } else if (((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ==
+                            (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ||
+                           (retp & BDRV_BLOCK_OFFSET_VALID)) {
                     /* Extend pnum to end of cluster for next iteration */
                     pnum = ROUND_UP(offset + pnum, cluster_size) - offset;
 
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-03-27  9:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-05 13:25 [PATCH v2 1/2] qcow2: handle discard-no-unref in measure Jean-Louis Dupond
2024-06-05 13:25 ` [PATCH v2 2/2] qcow2: don't allow discard-no-unref when discard is not enabled Jean-Louis Dupond
2024-07-10 13:00   ` Hanna Czenczek
2025-02-17 15:35     ` Jean-Louis Dupond
2024-07-10 12:58 ` [PATCH v2 1/2] qcow2: handle discard-no-unref in measure Hanna Czenczek
2025-02-17 15:34   ` Jean-Louis Dupond
2025-03-27  9:16     ` Jean-Louis Dupond

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).