diff options
author | Max Reitz <mreitz@redhat.com> | 2017-06-13 22:21:03 +0200 |
---|---|---|
committer | Max Reitz <mreitz@redhat.com> | 2017-07-11 17:45:02 +0200 |
commit | 12cc30a8cbdbb4c9c90cbffb970dfa679a1e3212 (patch) | |
tree | c11d287f068c09839334b15e1a0ab1934d35f3a6 /block/qcow2.c | |
parent | 95b98f343b054e100a905181cd140c653c80cbad (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.c | 20 |
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; } |