aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2017-06-13 22:21:03 +0200
committerMax Reitz <mreitz@redhat.com>2017-07-11 17:45:02 +0200
commit12cc30a8cbdbb4c9c90cbffb970dfa679a1e3212 (patch)
treec11d287f068c09839334b15e1a0ab1934d35f3a6 /block/qcow2.c
parent95b98f343b054e100a905181cd140c653c80cbad (diff)
block/qcow2: Add qcow2_refcount_area()
This function creates a collection of self-describing refcount structures (including a new refcount table) at the end of a qcow2 image file. Optionally, these structures can also describe a number of additional clusters beyond themselves; this will be important for preallocated truncation, which will place the data clusters and L2 tables there. For now, we can use this function to replace the part of alloc_refcount_block() that grows the refcount table (from which it is actually derived). Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 20170613202107.10125-13-mreitz@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
Diffstat (limited to 'block/qcow2.c')
-rw-r--r--block/qcow2.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/block/qcow2.c b/block/qcow2.c
index 47537d0a3f..46edea8dec 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2559,12 +2559,14 @@ done:
* @clusters: number of clusters to refcount (including data and L1/L2 tables)
* @cluster_size: size of a cluster, in bytes
* @refcount_order: refcount bits power-of-2 exponent
+ * @generous_increase: allow for the refcount table to be 1.5x as large as it
+ * needs to be
*
* Returns: Number of bytes required for refcount blocks and table metadata.
*/
-static int64_t qcow2_refcount_metadata_size(int64_t clusters,
- size_t cluster_size,
- int refcount_order)
+int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size,
+ int refcount_order, bool generous_increase,
+ uint64_t *refblock_count)
{
/*
* Every host cluster is reference-counted, including metadata (even
@@ -2587,8 +2589,18 @@ static int64_t qcow2_refcount_metadata_size(int64_t clusters,
blocks = DIV_ROUND_UP(clusters + table + blocks, refcounts_per_block);
table = DIV_ROUND_UP(blocks, blocks_per_table_cluster);
n = clusters + blocks + table;
+
+ if (n == last && generous_increase) {
+ clusters += DIV_ROUND_UP(table, 2);
+ n = 0; /* force another loop */
+ generous_increase = false;
+ }
} while (n != last);
+ if (refblock_count) {
+ *refblock_count = blocks;
+ }
+
return (blocks + table) * cluster_size;
}
@@ -2625,7 +2637,7 @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size,
/* total size of refcount table and blocks */
meta_size += qcow2_refcount_metadata_size(
(meta_size + aligned_total_size) / cluster_size,
- cluster_size, refcount_order);
+ cluster_size, refcount_order, false, NULL);
return meta_size + aligned_total_size;
}