From patchwork Tue Feb 13 17:05:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 873097 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 3zgr7f6wFbz9sQm for ; Wed, 14 Feb 2018 05:06:06 +1100 (AEDT) Received: from localhost ([::1]:57079 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elexw-0003YK-Or for incoming@patchwork.ozlabs.org; Tue, 13 Feb 2018 13:06:04 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53187) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ele2D-0003ZQ-Ow for qemu-devel@nongnu.org; Tue, 13 Feb 2018 12:06:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ele2B-0005kq-EK for qemu-devel@nongnu.org; Tue, 13 Feb 2018 12:06:25 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50800 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ele26-0005fo-Uw; Tue, 13 Feb 2018 12:06:19 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8EEFFEB700; Tue, 13 Feb 2018 17:06:18 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-94.ams2.redhat.com [10.36.117.94]) by smtp.corp.redhat.com (Postfix) with ESMTP id DEEA810075C2; Tue, 13 Feb 2018 17:06:17 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 13 Feb 2018 18:05:20 +0100 Message-Id: <20180213170529.10858-47-kwolf@redhat.com> In-Reply-To: <20180213170529.10858-1-kwolf@redhat.com> References: <20180213170529.10858-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Tue, 13 Feb 2018 17:06:18 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Tue, 13 Feb 2018 17:06:18 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 46/55] qcow2: Update expand_zero_clusters_in_l1() to support L2 slices X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Alberto Garcia expand_zero_clusters_in_l1() expands zero clusters as a necessary step to downgrade qcow2 images to a version that doesn't support metadata zero clusters. This function takes an L1 table (which may or may not be active) and iterates over all its L2 tables looking for zero clusters. Since we'll be loading L2 slices instead of full tables we need to add an extra loop that iterates over all slices of each L2 table, and we should also use the slice size when allocating the buffer used when the L1 table is not active. This function doesn't need any additional changes so apart from that this patch simply updates the variable name from l2_table to l2_slice. Finally, and since we have to touch the bdrv_read() / bdrv_write() calls anyway, this patch takes the opportunity to replace them with the byte-based bdrv_pread() / bdrv_pwrite(). Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake Reviewed-by: Max Reitz Message-id: 43590976f730501688096cff103f2923b72b0f32.1517840877.git.berto@igalia.com Signed-off-by: Max Reitz --- block/qcow2-cluster.c | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index ccb2944eda..8fbaba008b 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1863,22 +1863,25 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, { BDRVQcow2State *s = bs->opaque; bool is_active_l1 = (l1_table == s->l1_table); - uint64_t *l2_table = NULL; + uint64_t *l2_slice = NULL; + unsigned slice, slice_size2, n_slices; int ret; int i, j; + slice_size2 = s->l2_slice_size * sizeof(uint64_t); + n_slices = s->cluster_size / slice_size2; + if (!is_active_l1) { /* inactive L2 tables require a buffer to be stored in when loading * them from disk */ - l2_table = qemu_try_blockalign(bs->file->bs, s->cluster_size); - if (l2_table == NULL) { + l2_slice = qemu_try_blockalign(bs->file->bs, slice_size2); + if (l2_slice == NULL) { return -ENOMEM; } } for (i = 0; i < l1_size; i++) { uint64_t l2_offset = l1_table[i] & L1E_OFFSET_MASK; - bool l2_dirty = false; uint64_t l2_refcount; if (!l2_offset) { @@ -1904,22 +1907,23 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, goto fail; } - { + for (slice = 0; slice < n_slices; slice++) { + uint64_t slice_offset = l2_offset + slice * slice_size2; + bool l2_dirty = false; if (is_active_l1) { /* get active L2 tables from cache */ - ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, - (void **)&l2_table); + ret = qcow2_cache_get(bs, s->l2_table_cache, slice_offset, + (void **)&l2_slice); } else { /* load inactive L2 tables from disk */ - ret = bdrv_read(bs->file, l2_offset / BDRV_SECTOR_SIZE, - (void *)l2_table, s->cluster_sectors); + ret = bdrv_pread(bs->file, slice_offset, l2_slice, slice_size2); } if (ret < 0) { goto fail; } - for (j = 0; j < s->l2_size; j++) { - uint64_t l2_entry = be64_to_cpu(l2_table[j]); + for (j = 0; j < s->l2_slice_size; j++) { + uint64_t l2_entry = be64_to_cpu(l2_slice[j]); int64_t offset = l2_entry & L2E_OFFSET_MASK; QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry); @@ -1933,7 +1937,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, if (!bs->backing) { /* not backed; therefore we can simply deallocate the * cluster */ - l2_table[j] = 0; + l2_slice[j] = 0; l2_dirty = true; continue; } @@ -1960,12 +1964,13 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, } if (offset_into_cluster(s, offset)) { + int l2_index = slice * s->l2_slice_size + j; qcow2_signal_corruption( bs, true, -1, -1, "Cluster allocation offset " "%#" PRIx64 " unaligned (L2 offset: %#" PRIx64 ", L2 index: %#x)", offset, - l2_offset, j); + l2_offset, l2_index); if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) { qcow2_free_clusters(bs, offset, s->cluster_size, QCOW2_DISCARD_ALWAYS); @@ -1994,30 +1999,30 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, } if (l2_refcount == 1) { - l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); + l2_slice[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); } else { - l2_table[j] = cpu_to_be64(offset); + l2_slice[j] = cpu_to_be64(offset); } l2_dirty = true; } if (is_active_l1) { if (l2_dirty) { - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); qcow2_cache_depends_on_flush(s->l2_table_cache); } - qcow2_cache_put(s->l2_table_cache, (void **) &l2_table); + qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); } else { if (l2_dirty) { ret = qcow2_pre_write_overlap_check( bs, QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2, - l2_offset, s->cluster_size); + slice_offset, slice_size2); if (ret < 0) { goto fail; } - ret = bdrv_write(bs->file, l2_offset / BDRV_SECTOR_SIZE, - (void *)l2_table, s->cluster_sectors); + ret = bdrv_pwrite(bs->file, slice_offset, + l2_slice, slice_size2); if (ret < 0) { goto fail; } @@ -2034,11 +2039,11 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, ret = 0; fail: - if (l2_table) { + if (l2_slice) { if (!is_active_l1) { - qemu_vfree(l2_table); + qemu_vfree(l2_slice); } else { - qcow2_cache_put(s->l2_table_cache, (void **) &l2_table); + qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); } } return ret;