From nobody Fri Nov 14 16:59:39 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1588701068; cv=none; d=zohomail.com; s=zohoarc; b=YJWtK0RwPUV3LO6ZcKxQXf+f5G3HbL9OoAmNBzLYfPnvZ7I0Uvu4T7ylV1Kfj/nOSzC7U6oJVOwui3IiQCGh7vzDbufil0FQF02B8PowRcKShWtXyj0J94B/LAVvOEK7Zb+qCeTbEl3DEYsMshDBhsifRSjSwWZM24VfKKs1wTs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1588701068; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=4sKOqXVc3KxFwe8m3PYyTcs9/SZ04RD96n1xHNI7XXc=; b=cBsvmHDIx5ZVrqVy3WlupqckutsUkAzvkWDa+jNgbeaBZsOgNwZL4neAO6gVXO/An8eyYVVT46Ii6VtXxsTWhe9zpJSjXYoem0u3WK9hCrJ6VEXES1yoOyDFDpRa2Fm3EIfBDwOVZYaSqW4FkP24lqpfKO/T7JO11Ie9QNKogfA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1588701068987737.2489360625466; Tue, 5 May 2020 10:51:08 -0700 (PDT) Received: from localhost ([::1]:45864 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jW1il-0006sa-LN for importer@patchew.org; Tue, 05 May 2020 13:51:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:44008) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jW1XN-0006Hr-6C; Tue, 05 May 2020 13:39:21 -0400 Received: from fanzine.igalia.com ([178.60.130.6]:38918) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jW1XJ-0008Dz-98; Tue, 05 May 2020 13:39:20 -0400 Received: from static.160.43.0.81.ibercom.com ([81.0.43.160] helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1jW1Ws-00025J-Er; Tue, 05 May 2020 19:38:50 +0200 Received: from berto by perseus.local with local (Exim 4.92) (envelope-from ) id 1jW1Wc-00043v-QX; Tue, 05 May 2020 19:38:34 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=4sKOqXVc3KxFwe8m3PYyTcs9/SZ04RD96n1xHNI7XXc=; b=YRHZbRweovnKppufSWEDldbnzPRtN35BwWM45SuZ9LHBD/GZAEWu06t4ddmp0EdpRkKtoHCY4KNH8JiWgRWrQM7XOBTFeKzVlSxFViOKcezOqL9i2Ai2gdD/dhZV+TJwH/nPaV7oljVgDpFUFdrhqYPyuiOonoG6Zg+zUexYAWFux7dxOghz/50PCswTZgF4K5N9o8JBPoVpXm4QcKFBYpzHWY837hzPPus3kNdF3nKmItitNtkco2kSvENNHmKFeQNPWMykHXxD3GpTwdTeS7369cE3BOSJ7Rl5KwHAjRrWtOGiRGigA6seZSu/J+RAtw+tvAyW0Noia5NS7Y9CWA==; From: Alberto Garcia To: qemu-devel@nongnu.org Subject: [PATCH v5 12/31] qcow2: Add l2_entry_size() Date: Tue, 5 May 2020 19:38:12 +0200 Message-Id: <7c811bad2c9ceab5c08d9ef56d67bce73f2e3d6d.1588699789.git.berto@igalia.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=178.60.130.6; envelope-from=berto@igalia.com; helo=fanzine.igalia.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/05 13:38:50 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Vladimir Sementsov-Ogievskiy , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" qcow2 images with subclusters have 128-bit L2 entries. The first 64 bits contain the same information as traditional images and the last 64 bits form a bitmap with the status of each individual subcluster. Because of that we cannot assume that L2 entries are sizeof(uint64_t) anymore. This function returns the proper value for the image. Signed-off-by: Alberto Garcia Reviewed-by: Max Reitz --- block/qcow2.h | 9 +++++++++ block/qcow2-cluster.c | 12 ++++++------ block/qcow2-refcount.c | 14 ++++++++------ block/qcow2.c | 8 ++++---- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/block/qcow2.h b/block/qcow2.h index 8b1ed1cbcf..80ceb352c9 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -80,6 +80,10 @@ =20 #define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32 =20 +/* Size of normal and extended L2 entries */ +#define L2E_SIZE_NORMAL (sizeof(uint64_t)) +#define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2) + #define MIN_CLUSTER_BITS 9 #define MAX_CLUSTER_BITS 21 =20 @@ -503,6 +507,11 @@ static inline bool has_subclusters(BDRVQcow2State *s) return false; } =20 +static inline size_t l2_entry_size(BDRVQcow2State *s) +{ + return has_subclusters(s) ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL; +} + static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice, int idx) { diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 76fd0f3cdb..8b2fc550b7 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -208,7 +208,7 @@ static int l2_load(BlockDriverState *bs, uint64_t offse= t, uint64_t l2_offset, uint64_t **l2_slice) { BDRVQcow2State *s =3D bs->opaque; - int start_of_slice =3D sizeof(uint64_t) * + int start_of_slice =3D l2_entry_size(s) * (offset_to_l2_index(s, offset) - offset_to_l2_slice_index(s, offse= t)); =20 return qcow2_cache_get(bs, s->l2_table_cache, l2_offset + start_of_sli= ce, @@ -281,7 +281,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_ind= ex) =20 /* allocate a new l2 entry */ =20 - l2_offset =3D qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t)); + l2_offset =3D qcow2_alloc_clusters(bs, s->l2_size * l2_entry_size(s)); if (l2_offset < 0) { ret =3D l2_offset; goto fail; @@ -305,7 +305,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_ind= ex) =20 /* allocate a new entry in the l2 cache */ =20 - slice_size2 =3D s->l2_slice_size * sizeof(uint64_t); + slice_size2 =3D s->l2_slice_size * l2_entry_size(s); n_slices =3D s->cluster_size / slice_size2; =20 trace_qcow2_l2_allocate_get_empty(bs, l1_index); @@ -369,7 +369,7 @@ fail: } s->l1_table[l1_index] =3D old_l2_offset; if (l2_offset > 0) { - qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t), + qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s), QCOW2_DISCARD_ALWAYS); } return ret; @@ -716,7 +716,7 @@ static int get_cluster_table(BlockDriverState *bs, uint= 64_t offset, =20 /* Then decrease the refcount of the old table */ if (l2_offset) { - qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_= t), + qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(= s), QCOW2_DISCARD_OTHER); } =20 @@ -1913,7 +1913,7 @@ static int expand_zero_clusters_in_l1(BlockDriverStat= e *bs, uint64_t *l1_table, int ret; int i, j; =20 - slice_size2 =3D s->l2_slice_size * sizeof(uint64_t); + slice_size2 =3D s->l2_slice_size * l2_entry_size(s); n_slices =3D s->cluster_size / slice_size2; =20 if (!is_active_l1) { diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index b299b9bda4..dfdcdd3c25 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1254,7 +1254,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *= bs, l2_slice =3D NULL; l1_table =3D NULL; l1_size2 =3D l1_size * sizeof(uint64_t); - slice_size2 =3D s->l2_slice_size * sizeof(uint64_t); + slice_size2 =3D s->l2_slice_size * l2_entry_size(s); n_slices =3D s->cluster_size / slice_size2; =20 s->cache_discards =3D true; @@ -1605,7 +1605,7 @@ static int check_refcounts_l2(BlockDriverState *bs, B= drvCheckResult *res, int i, l2_size, nb_csectors, ret; =20 /* Read L2 table from disk */ - l2_size =3D s->l2_size * sizeof(uint64_t); + l2_size =3D s->l2_size * l2_entry_size(s); l2_table =3D g_malloc(l2_size); =20 ret =3D bdrv_pread(bs->file, l2_offset, l2_table, l2_size); @@ -1680,15 +1680,16 @@ static int check_refcounts_l2(BlockDriverState *bs,= BdrvCheckResult *res, fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", offset); if (fix & BDRV_FIX_ERRORS) { + int idx =3D i * (l2_entry_size(s) / sizeof(uint64_= t)); uint64_t l2e_offset =3D - l2_offset + (uint64_t)i * sizeof(uint64_t); + l2_offset + (uint64_t)i * l2_entry_size(s); int ign =3D active ? QCOW2_OL_ACTIVE_L2 : QCOW2_OL_INACTIVE_L2; =20 l2_entry =3D QCOW_OFLAG_ZERO; set_l2_entry(s, l2_table, i, l2_entry); ret =3D qcow2_pre_write_overlap_check(bs, ign, - l2e_offset, sizeof(uint64_t), false); + l2e_offset, l2_entry_size(s), false); if (ret < 0) { fprintf(stderr, "ERROR: Overlap check failed\n= "); res->check_errors++; @@ -1698,7 +1699,8 @@ static int check_refcounts_l2(BlockDriverState *bs, B= drvCheckResult *res, } =20 ret =3D bdrv_pwrite_sync(bs->file, l2e_offset, - &l2_table[i], sizeof(uint64= _t)); + &l2_table[idx], + l2_entry_size(s)); if (ret < 0) { fprintf(stderr, "ERROR: Failed to overwrite L2= " "table entry: %s\n", strerror(-ret)); @@ -1905,7 +1907,7 @@ static int check_oflag_copied(BlockDriverState *bs, B= drvCheckResult *res, } =20 ret =3D bdrv_pread(bs->file, l2_offset, l2_table, - s->l2_size * sizeof(uint64_t)); + s->l2_size * l2_entry_size(s)); if (ret < 0) { fprintf(stderr, "ERROR: Could not read L2 table: %s\n", strerror(-ret)); diff --git a/block/qcow2.c b/block/qcow2.c index e5ae8aaff7..9a8fb5a7bf 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -870,7 +870,7 @@ static void read_cache_sizes(BlockDriverState *bs, Qemu= Opts *opts, uint64_t max_l2_entries =3D DIV_ROUND_UP(virtual_disk_size, s->cluster= _size); /* An L2 table is always one cluster in size so the max cache size * should be a multiple of the cluster size. */ - uint64_t max_l2_cache =3D ROUND_UP(max_l2_entries * sizeof(uint64_t), + uint64_t max_l2_cache =3D ROUND_UP(max_l2_entries * l2_entry_size(s), s->cluster_size); =20 combined_cache_size_set =3D qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE); @@ -1031,7 +1031,7 @@ static int qcow2_update_options_prepare(BlockDriverSt= ate *bs, } } =20 - r->l2_slice_size =3D l2_cache_entry_size / sizeof(uint64_t); + r->l2_slice_size =3D l2_cache_entry_size / l2_entry_size(s); r->l2_table_cache =3D qcow2_cache_create(bs, l2_cache_size, l2_cache_entry_size); r->refcount_block_cache =3D qcow2_cache_create(bs, refcount_cache_size, @@ -1425,7 +1425,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverStat= e *bs, QDict *options, bs->encrypted =3D true; } =20 - s->l2_bits =3D s->cluster_bits - 3; /* L2 is always one cluster */ + s->l2_bits =3D s->cluster_bits - ctz32(l2_entry_size(s)); s->l2_size =3D 1 << s->l2_bits; /* 2^(s->refcount_order - 3) is the refcount width in bytes */ s->refcount_block_bits =3D s->cluster_bits - (s->refcount_order - 3); @@ -4132,7 +4132,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriver= State *bs, int64_t offset, * preallocation. All that matters is that we will not have to al= locate * new refcount structures for them.) */ nb_new_l2_tables =3D DIV_ROUND_UP(nb_new_data_clusters, - s->cluster_size / sizeof(uint64_t)= ); + s->cluster_size / l2_entry_size(s)= ); /* The cluster range may not be aligned to L2 boundaries, so add o= ne L2 * table for a potential head/tail */ nb_new_l2_tables++; --=20 2.20.1