All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
To: qemu-block@nongnu.org, qemu-devel@nongnu.org
Cc: pbutsykin@virtuozzo.com, kwolf@redhat.com, mreitz@redhat.com,
	eblake@redhat.com, den@openvz.org
Subject: [Qemu-devel] [PATCH 2/2] qcow2: truncate the tail of the image file after shrinking the image
Date: Wed, 20 Sep 2017 16:58:33 +0300	[thread overview]
Message-ID: <20170920135833.20472-3-pbutsykin@virtuozzo.com> (raw)
In-Reply-To: <20170920135833.20472-1-pbutsykin@virtuozzo.com>

Now after shrinking the image, at the end of the image file, there might be a
tail that probably will never be used. So we can find the last used cluster and
cut the tail.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
---
 block/qcow2-refcount.c | 21 +++++++++++++++++++++
 block/qcow2.c          | 19 +++++++++++++++++++
 block/qcow2.h          |  1 +
 3 files changed, 41 insertions(+)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 88d5a3f1ad..5e221a166c 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -3181,3 +3181,24 @@ out:
     g_free(reftable_tmp);
     return ret;
 }
+
+int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size)
+{
+    BDRVQcow2State *s = bs->opaque;
+    int64_t i, last_cluster, nb_clusters = size_to_clusters(s, size);
+    uint64_t refcount;
+
+    for (i = 0, last_cluster = 0; i < nb_clusters; i++) {
+        int ret = qcow2_get_refcount(bs, i, &refcount);
+        if (ret < 0) {
+            fprintf(stderr, "Can't get refcount for cluster %" PRId64 ": %s\n",
+                    i, strerror(-ret));
+            continue;
+        }
+
+        if (refcount > 0) {
+            last_cluster = i;
+        }
+    }
+    return last_cluster;
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index 8a4311d338..c3b6dd44c4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3106,6 +3106,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
     new_l1_size = size_to_l1(s, offset);
 
     if (offset < old_length) {
+        int64_t image_end_offset, old_file_size;
         if (prealloc != PREALLOC_MODE_OFF) {
             error_setg(errp,
                        "Preallocation can't be used for shrinking an image");
@@ -3134,6 +3135,24 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
                              "Failed to discard unused refblocks");
             return ret;
         }
+
+        old_file_size = bdrv_getlength(bs->file->bs);
+        if (old_file_size < 0) {
+            error_setg_errno(errp, -old_file_size,
+                             "Failed to inquire current file length");
+            return old_file_size;
+        }
+        image_end_offset = (qcow2_get_last_cluster(bs, old_file_size) + 1) *
+                           s->cluster_size;
+        if (image_end_offset < old_file_size) {
+            ret = bdrv_truncate(bs->file, image_end_offset,
+                                PREALLOC_MODE_OFF, NULL);
+            if (ret < 0) {
+                error_setg_errno(errp, -ret,
+                                 "Failed to truncate the tail of the image");
+                return ret;
+            }
+        }
     } else {
         ret = qcow2_grow_l1_table(bs, new_l1_size, true);
         if (ret < 0) {
diff --git a/block/qcow2.h b/block/qcow2.h
index 5a289a81e2..782a206ecb 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -597,6 +597,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
                                 BlockDriverAmendStatusCB *status_cb,
                                 void *cb_opaque, Error **errp);
 int qcow2_shrink_reftable(BlockDriverState *bs);
+int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
 
 /* qcow2-cluster.c functions */
 int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
-- 
2.14.1

  parent reply	other threads:[~2017-09-20 13:58 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-20 13:58 [Qemu-devel] [PATCH 0/2] Truncate the tail of the image file in qcow2 shrinking Pavel Butsykin
2017-09-20 13:58 ` [Qemu-devel] [PATCH 1/2] qcow2: fix return error code in qcow2_truncate() Pavel Butsykin
2017-09-20 14:27   ` Eric Blake
2017-09-20 20:17   ` [Qemu-devel] [Qemu-block] " John Snow
2017-09-21 15:28   ` [Qemu-devel] " Max Reitz
2017-09-20 13:58 ` Pavel Butsykin [this message]
2017-09-20 21:38   ` [Qemu-devel] [Qemu-block] [PATCH 2/2] qcow2: truncate the tail of the image file after shrinking the image John Snow
2017-09-21  9:49     ` Pavel Butsykin
2017-09-21 16:48       ` John Snow
2017-09-21 18:23         ` Eric Blake
2017-09-21 15:28   ` [Qemu-devel] " Max Reitz
2017-09-21 16:16     ` Pavel Butsykin
2017-09-21 16:20       ` Max Reitz
2017-09-21 15:30   ` Max Reitz
2017-09-21 15:52     ` Pavel Butsykin

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=20170920135833.20472-3-pbutsykin@virtuozzo.com \
    --to=pbutsykin@virtuozzo.com \
    --cc=den@openvz.org \
    --cc=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.