qcow2: extract preallocation calculation function
Calculating the preallocated image size will be needed to implement .bdrv_measure(). Extract the code out into a separate function. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Message-id: 20170705125738.8777-4-stefanha@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
a843a22a82
commit
95c67e3bd7
@ -2537,44 +2537,19 @@ static int preallocate(BlockDriverState *bs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcow2_create2(const char *filename, int64_t total_size,
|
/**
|
||||||
const char *backing_file, const char *backing_format,
|
* qcow2_calc_prealloc_size:
|
||||||
int flags, size_t cluster_size, PreallocMode prealloc,
|
* @total_size: virtual disk size in bytes
|
||||||
QemuOpts *opts, int version, int refcount_order,
|
* @cluster_size: cluster size in bytes
|
||||||
const char *encryptfmt, Error **errp)
|
* @refcount_order: refcount bits power-of-2 exponent
|
||||||
{
|
|
||||||
int cluster_bits;
|
|
||||||
QDict *options;
|
|
||||||
|
|
||||||
/* Calculate cluster_bits */
|
|
||||||
cluster_bits = ctz32(cluster_size);
|
|
||||||
if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||
|
|
||||||
(1 << cluster_bits) != cluster_size)
|
|
||||||
{
|
|
||||||
error_setg(errp, "Cluster size must be a power of two between %d and "
|
|
||||||
"%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the image file and write a minimal qcow2 header.
|
|
||||||
*
|
*
|
||||||
* We keep things simple and start with a zero-sized image. We also
|
* Returns: Total number of bytes required for the fully allocated image
|
||||||
* do without refcount blocks or a L1 table for now. We'll fix the
|
* (including metadata).
|
||||||
* inconsistency later.
|
|
||||||
*
|
|
||||||
* We do need a refcount table because growing the refcount table means
|
|
||||||
* allocating two new refcount blocks - the seconds of which would be at
|
|
||||||
* 2 GB for 64k clusters, and we don't want to have a 2 GB initial file
|
|
||||||
* size for any qcow2 image.
|
|
||||||
*/
|
*/
|
||||||
BlockBackend *blk;
|
static int64_t qcow2_calc_prealloc_size(int64_t total_size,
|
||||||
QCowHeader *header;
|
size_t cluster_size,
|
||||||
uint64_t* refcount_table;
|
int refcount_order)
|
||||||
Error *local_err = NULL;
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {
|
|
||||||
/* Note: The following calculation does not need to be exact; if it is a
|
/* Note: The following calculation does not need to be exact; if it is a
|
||||||
* bit off, either some bytes will be "leaked" (which is fine) or we
|
* bit off, either some bytes will be "leaked" (which is fine) or we
|
||||||
* will need to increase the file size by some bytes (which is fine,
|
* will need to increase the file size by some bytes (which is fine,
|
||||||
@ -2583,6 +2558,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
|||||||
int64_t meta_size = 0;
|
int64_t meta_size = 0;
|
||||||
uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count;
|
uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count;
|
||||||
int64_t aligned_total_size = align_offset(total_size, cluster_size);
|
int64_t aligned_total_size = align_offset(total_size, cluster_size);
|
||||||
|
int cluster_bits = ctz32(cluster_size);
|
||||||
int refblock_bits, refblock_size;
|
int refblock_bits, refblock_size;
|
||||||
/* refcount entry size in bytes */
|
/* refcount entry size in bytes */
|
||||||
double rces = (1 << refcount_order) / 8.;
|
double rces = (1 << refcount_order) / 8.;
|
||||||
@ -2632,8 +2608,50 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
|||||||
cluster_size / sizeof(uint64_t));
|
cluster_size / sizeof(uint64_t));
|
||||||
meta_size += nreftablee * sizeof(uint64_t);
|
meta_size += nreftablee * sizeof(uint64_t);
|
||||||
|
|
||||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
|
return meta_size + aligned_total_size;
|
||||||
aligned_total_size + meta_size, &error_abort);
|
}
|
||||||
|
|
||||||
|
static int qcow2_create2(const char *filename, int64_t total_size,
|
||||||
|
const char *backing_file, const char *backing_format,
|
||||||
|
int flags, size_t cluster_size, PreallocMode prealloc,
|
||||||
|
QemuOpts *opts, int version, int refcount_order,
|
||||||
|
const char *encryptfmt, Error **errp)
|
||||||
|
{
|
||||||
|
int cluster_bits;
|
||||||
|
QDict *options;
|
||||||
|
|
||||||
|
/* Calculate cluster_bits */
|
||||||
|
cluster_bits = ctz32(cluster_size);
|
||||||
|
if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||
|
||||||
|
(1 << cluster_bits) != cluster_size)
|
||||||
|
{
|
||||||
|
error_setg(errp, "Cluster size must be a power of two between %d and "
|
||||||
|
"%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the image file and write a minimal qcow2 header.
|
||||||
|
*
|
||||||
|
* We keep things simple and start with a zero-sized image. We also
|
||||||
|
* do without refcount blocks or a L1 table for now. We'll fix the
|
||||||
|
* inconsistency later.
|
||||||
|
*
|
||||||
|
* We do need a refcount table because growing the refcount table means
|
||||||
|
* allocating two new refcount blocks - the seconds of which would be at
|
||||||
|
* 2 GB for 64k clusters, and we don't want to have a 2 GB initial file
|
||||||
|
* size for any qcow2 image.
|
||||||
|
*/
|
||||||
|
BlockBackend *blk;
|
||||||
|
QCowHeader *header;
|
||||||
|
uint64_t* refcount_table;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {
|
||||||
|
int64_t prealloc_size =
|
||||||
|
qcow2_calc_prealloc_size(total_size, cluster_size, refcount_order);
|
||||||
|
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
|
||||||
qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_lookup[prealloc],
|
qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_lookup[prealloc],
|
||||||
&error_abort);
|
&error_abort);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user