summaryrefslogtreecommitdiff
path: root/block/qcow2-cluster.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@linux.vnet.ibm.com>2010-10-18 16:53:53 +0100
committerKevin Wolf <kwolf@redhat.com>2010-10-22 14:49:35 +0200
commit72893756e0da74fcb626c52dfff1fc6e9de84f0c (patch)
treeca761120b722477d05c62f2a1d9cd25bd5352ee3 /block/qcow2-cluster.c
parentd03703c81a202cea156811e5dbc8e88627c19986 (diff)
qcow2: Support exact L1 table growth
The L1 table grow operation includes a size calculation that bumps up the new L1 table size in order to anticipate the size needs of vmstate data. This helps reduce the number of times that the L1 table has to be grown when vmstate data is appended. This size overhead is not necessary during image creation, bdrv_truncate(), or snapshot goto operations. In fact, existing qemu-iotests that exercise table growth are no longer able to trigger it because image creation preallocates an L1 table that is too large after changes to qcow_create2(). This patch keeps the size calculation but also adds exact growth for callers that do not want to inflate the L1 table size unnecessarily. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/qcow2-cluster.c')
-rw-r--r--block/qcow2-cluster.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index fb4224a669..4f7dc59b76 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -28,7 +28,7 @@
#include "block_int.h"
#include "block/qcow2.h"
-int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
+int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
{
BDRVQcowState *s = bs->opaque;
int new_l1_size, new_l1_size2, ret, i;
@@ -36,15 +36,22 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
int64_t new_l1_table_offset;
uint8_t data[12];
- new_l1_size = s->l1_size;
- if (min_size <= new_l1_size)
+ if (min_size <= s->l1_size)
return 0;
- if (new_l1_size == 0) {
- new_l1_size = 1;
- }
- while (min_size > new_l1_size) {
- new_l1_size = (new_l1_size * 3 + 1) / 2;
+
+ if (exact_size) {
+ new_l1_size = min_size;
+ } else {
+ /* Bump size up to reduce the number of times we have to grow */
+ new_l1_size = s->l1_size;
+ if (new_l1_size == 0) {
+ new_l1_size = 1;
+ }
+ while (min_size > new_l1_size) {
+ new_l1_size = (new_l1_size * 3 + 1) / 2;
+ }
}
+
#ifdef DEBUG_ALLOC2
printf("grow l1_table from %d to %d\n", s->l1_size, new_l1_size);
#endif
@@ -550,7 +557,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);
+ ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
if (ret < 0) {
return ret;
}