diff options
Diffstat (limited to 'block/qcow2-cluster.c')
-rw-r--r-- | block/qcow2-cluster.c | 25 |
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; } |