From patchwork Tue Apr 1 13:30:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: lijun X-Patchwork-Id: 336355 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D9E6114010E for ; Thu, 3 Apr 2014 01:12:40 +1100 (EST) Received: from localhost ([::1]:38888 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WVLu9-0007CB-R5 for incoming@patchwork.ozlabs.org; Wed, 02 Apr 2014 10:12:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53243) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WVLtb-00074R-8D for qemu-devel@nongnu.org; Wed, 02 Apr 2014 10:12:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WVLtV-0000ZV-15 for qemu-devel@nongnu.org; Wed, 02 Apr 2014 10:12:03 -0400 Received: from [111.204.254.34] (port=7075 helo=localhost.localdomain) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WVLtT-0000Z5-Sw for qemu-devel@nongnu.org; Wed, 02 Apr 2014 10:11:56 -0400 Received: from localhost.localdomain (localhost [127.0.0.1]) by localhost.localdomain (8.14.7/8.14.7) with ESMTP id s31DUiTA002891; Tue, 1 Apr 2014 21:30:44 +0800 Received: (from lijun@localhost) by localhost.localdomain (8.14.7/8.14.7/Submit) id s31DUb4R002890; Tue, 1 Apr 2014 21:30:37 +0800 From: Jun Li To: kwolf@redhat.com, stefanha@redhat.com Date: Tue, 1 Apr 2014 21:30:33 +0800 Message-Id: <1396359033-2854-1-git-send-email-junmuzi@gmail.com> X-Mailer: git-send-email 1.8.3.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 111.204.254.34 Cc: Jun Li , qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH] Patch for shrinking qcow2 disk image X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Jun Li This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change. As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table. --- block/qcow2-cluster.c | 20 ++++++++++++++------ block/qcow2-snapshot.c | 2 +- block/qcow2.c | 8 +------- block/qcow2.h | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 9499df9..70e61ea 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -29,7 +29,7 @@ #include "block/qcow2.h" #include "trace.h" -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size) { BDRVQcowState *s = bs->opaque; @@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, int64_t new_l1_table_offset, new_l1_size; uint8_t data[12]; - if (min_size <= s->l1_size) - return 0; - if (exact_size) { new_l1_size = min_size; } else { @@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, new_l1_size2 = sizeof(uint64_t) * new_l1_size; new_l1_table = g_malloc0(align_offset(new_l1_size2, 512)); - memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); + + /* shrinking the image */ + if (min_size <= s->l1_size) { + if (s->l1_table[new_l1_size] != 0) { + error_report("Could not shrink to this size, " + "it will destory image data"); + return -ENOTSUP; + } + memcpy(new_l1_table, s->l1_table, new_l1_size2); + } + + memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); /* write new table (align to cluster) */ BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE); @@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, l1_index = offset >> (s->l2_bits + s->cluster_bits); if (l1_index >= s->l1_size) { - ret = qcow2_grow_l1_table(bs, l1_index + 1, false); + ret = qcow2_truncate_l1_table(bs, l1_index + 1, false); if (ret < 0) { return ret; } diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 2fc6320..ab16c52 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) * L1 table of the snapshot. If the snapshot L1 table is smaller, the * current one must be padded with zeros. */ - ret = qcow2_grow_l1_table(bs, sn->l1_size, true); + ret = qcow2_truncate_l1_table(bs, sn->l1_size, true); if (ret < 0) { goto fail; } diff --git a/block/qcow2.c b/block/qcow2.c index b9dc960..4797879 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset) return -ENOTSUP; } - /* shrinking is currently not supported */ - if (offset < bs->total_sectors * 512) { - error_report("qcow2 doesn't support shrinking images yet"); - return -ENOTSUP; - } - new_l1_size = size_to_l1(s, offset); - ret = qcow2_grow_l1_table(bs, new_l1_size, true); + ret = qcow2_truncate_l1_table(bs, new_l1_size, true); if (ret < 0) { return ret; } diff --git a/block/qcow2.h b/block/qcow2.h index 0b0eac8..298d84e 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, int64_t size); /* qcow2-cluster.c functions */ -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size); int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); void qcow2_l2_cache_reset(BlockDriverState *bs);