|
|
9ae3a8 |
From 6529ac40614e6b28a9c52de40defb6e2f455698b Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 7 Jan 2014 21:57:14 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 09/14] qcow2: Correct bitmap size in zero expansion
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1389131839-12920-10-git-send-email-mreitz@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 56545
|
|
|
9ae3a8 |
O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 09/14] qcow2: Correct bitmap size in zero expansion
|
|
|
9ae3a8 |
Bugzilla: 1033490
|
|
|
9ae3a8 |
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
BZ: 1033490
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Since the expanded_clusters bitmap is addressed using host offsets in
|
|
|
9ae3a8 |
the underlying image file, the correct size to use for allocating the
|
|
|
9ae3a8 |
bitmap is not determined by the guest disk image but by the underlying
|
|
|
9ae3a8 |
host image file.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Furthermore, this size may change during the expansion due to cluster
|
|
|
9ae3a8 |
allocations on growable image files. In this case, the bitmap needs to
|
|
|
9ae3a8 |
be resized as well to reflect the growth.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit e390cf5a9722d3f3cc54efb505f6ff37fa554b11)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/qcow2-cluster.c | 38 +++++++++++++++++++++++++++-----------
|
|
|
9ae3a8 |
1 file changed, 27 insertions(+), 11 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/qcow2-cluster.c | 38 +++++++++++++++++++++++++++-----------
|
|
|
9ae3a8 |
1 files changed, 27 insertions(+), 11 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
|
|
9ae3a8 |
index 796d7c5..bfdc83a 100644
|
|
|
9ae3a8 |
--- a/block/qcow2-cluster.c
|
|
|
9ae3a8 |
+++ b/block/qcow2-cluster.c
|
|
|
9ae3a8 |
@@ -1511,8 +1511,8 @@ fail:
|
|
|
9ae3a8 |
* i.e., the number of bits in expanded_clusters.
|
|
|
9ae3a8 |
*/
|
|
|
9ae3a8 |
static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
|
|
9ae3a8 |
- int l1_size, uint8_t *expanded_clusters,
|
|
|
9ae3a8 |
- uint64_t nb_clusters)
|
|
|
9ae3a8 |
+ int l1_size, uint8_t **expanded_clusters,
|
|
|
9ae3a8 |
+ uint64_t *nb_clusters)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
BDRVQcowState *s = bs->opaque;
|
|
|
9ae3a8 |
bool is_active_l1 = (l1_table == s->l1_table);
|
|
|
9ae3a8 |
@@ -1555,8 +1555,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (cluster_type == QCOW2_CLUSTER_NORMAL) {
|
|
|
9ae3a8 |
cluster_index = offset >> s->cluster_bits;
|
|
|
9ae3a8 |
- assert((cluster_index >= 0) && (cluster_index < nb_clusters));
|
|
|
9ae3a8 |
- if (expanded_clusters[cluster_index / 8] &
|
|
|
9ae3a8 |
+ assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
|
|
|
9ae3a8 |
+ if ((*expanded_clusters)[cluster_index / 8] &
|
|
|
9ae3a8 |
(1 << (cluster_index % 8))) {
|
|
|
9ae3a8 |
/* Probably a shared L2 table; this cluster was a zero
|
|
|
9ae3a8 |
* cluster which has been expanded, its refcount
|
|
|
9ae3a8 |
@@ -1613,8 +1613,25 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
|
|
9ae3a8 |
l2_dirty = true;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
cluster_index = offset >> s->cluster_bits;
|
|
|
9ae3a8 |
- assert((cluster_index >= 0) && (cluster_index < nb_clusters));
|
|
|
9ae3a8 |
- expanded_clusters[cluster_index / 8] |= 1 << (cluster_index % 8);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if (cluster_index >= *nb_clusters) {
|
|
|
9ae3a8 |
+ uint64_t old_bitmap_size = (*nb_clusters + 7) / 8;
|
|
|
9ae3a8 |
+ uint64_t new_bitmap_size;
|
|
|
9ae3a8 |
+ /* The offset may lie beyond the old end of the underlying image
|
|
|
9ae3a8 |
+ * file for growable files only */
|
|
|
9ae3a8 |
+ assert(bs->file->growable);
|
|
|
9ae3a8 |
+ *nb_clusters = size_to_clusters(s, bs->file->total_sectors *
|
|
|
9ae3a8 |
+ BDRV_SECTOR_SIZE);
|
|
|
9ae3a8 |
+ new_bitmap_size = (*nb_clusters + 7) / 8;
|
|
|
9ae3a8 |
+ *expanded_clusters = g_realloc(*expanded_clusters,
|
|
|
9ae3a8 |
+ new_bitmap_size);
|
|
|
9ae3a8 |
+ /* clear the newly allocated space */
|
|
|
9ae3a8 |
+ memset(&(*expanded_clusters)[old_bitmap_size], 0,
|
|
|
9ae3a8 |
+ new_bitmap_size - old_bitmap_size);
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
|
|
|
9ae3a8 |
+ (*expanded_clusters)[cluster_index / 8] |= 1 << (cluster_index % 8);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (is_active_l1) {
|
|
|
9ae3a8 |
@@ -1673,18 +1690,17 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
BDRVQcowState *s = bs->opaque;
|
|
|
9ae3a8 |
uint64_t *l1_table = NULL;
|
|
|
9ae3a8 |
- int cluster_to_sector_bits = s->cluster_bits - BDRV_SECTOR_BITS;
|
|
|
9ae3a8 |
uint64_t nb_clusters;
|
|
|
9ae3a8 |
uint8_t *expanded_clusters;
|
|
|
9ae3a8 |
int ret;
|
|
|
9ae3a8 |
int i, j;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- nb_clusters = (bs->total_sectors + (1 << cluster_to_sector_bits) - 1)
|
|
|
9ae3a8 |
- >> cluster_to_sector_bits;
|
|
|
9ae3a8 |
+ nb_clusters = size_to_clusters(s, bs->file->total_sectors *
|
|
|
9ae3a8 |
+ BDRV_SECTOR_SIZE);
|
|
|
9ae3a8 |
expanded_clusters = g_malloc0((nb_clusters + 7) / 8);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size,
|
|
|
9ae3a8 |
- expanded_clusters, nb_clusters);
|
|
|
9ae3a8 |
+ &expanded_clusters, &nb_clusters);
|
|
|
9ae3a8 |
if (ret < 0) {
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -1718,7 +1734,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size,
|
|
|
9ae3a8 |
- expanded_clusters, nb_clusters);
|
|
|
9ae3a8 |
+ &expanded_clusters, &nb_clusters);
|
|
|
9ae3a8 |
if (ret < 0) {
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|