From patchwork Fri May 9 15:20:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: lijun X-Patchwork-Id: 347444 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8B30914007C for ; Sat, 10 May 2014 01:21:37 +1000 (EST) Received: from localhost ([::1]:53097 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WimcB-0004FH-Cv for incoming@patchwork.ozlabs.org; Fri, 09 May 2014 11:21:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36609) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wimbp-0003ym-Dd for qemu-devel@nongnu.org; Fri, 09 May 2014 11:21:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Wimbj-0002RX-8T for qemu-devel@nongnu.org; Fri, 09 May 2014 11:21:13 -0400 Received: from [111.204.254.15] (port=53795 helo=localhost.localdomain) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wimbf-0002RI-Jz for qemu-devel@nongnu.org; Fri, 09 May 2014 11:21:07 -0400 Received: from localhost.localdomain (localhost [127.0.0.1]) by localhost.localdomain (8.14.7/8.14.7) with ESMTP id s49FKjvs016678; Fri, 9 May 2014 23:20:46 +0800 Received: (from root@localhost) by localhost.localdomain (8.14.7/8.14.7/Submit) id s49FKiYZ016677; Fri, 9 May 2014 23:20:44 +0800 From: Jun Li To: qemu-devel@nongnu.org Date: Fri, 9 May 2014 23:20:41 +0800 Message-Id: <1399648841-16640-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.15 Cc: kwolf@redhat.com, juli@redhat.com, famz@redhat.com, Jun Li , stefanha@redhat.com Subject: [Qemu-devel] [PATCH v2] qcow2: 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 As the realization of raw shrinking, so when do qcow2 shrinking, do not check l1 entries. When resize to size1(size1 < "disk size"), the custemer knows this will destory the data. So no need to check the l1 entries which is used or not. This is v2 of the original patch. thx. Signed-off-by: Jun Li --- block/qcow2-cluster.c | 17 ++++++++++++----- block/qcow2-snapshot.c | 2 +- block/qcow2.c | 10 ++-------- block/qcow2.h | 4 ++-- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 76d2bcf..8fbbf7f 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -29,8 +29,8 @@ #include "block/qcow2.h" #include "trace.h" -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, - bool exact_size) +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size, + bool exact_size) { BDRVQcowState *s = bs->opaque; int new_l1_size2, ret, i; @@ -39,8 +39,9 @@ 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) + if (min_size == s->l1_size) { return 0; + } /* Do a sanity check on min_size before trying to calculate new_l1_size * (this prevents overflows during the while loop for the calculation of @@ -73,7 +74,13 @@ 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 or growing l1 table */ + if (min_size < s->l1_size) { + memcpy(new_l1_table, s->l1_table, new_l1_size2); + } else { + 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); @@ -558,7 +565,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 0aa9def..6ba460e 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -483,7 +483,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 a4b97e8..70f951c 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1877,7 +1877,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset) int64_t new_l1_size; int ret; - if (offset & 511) { + if (offset <= 0 || offset & 511) { error_report("The new size must be a multiple of 512"); return -EINVAL; } @@ -1888,14 +1888,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 b49424b..fa36930 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -499,8 +499,8 @@ 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, - bool exact_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); int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);