[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH v4 4/4] qcow2: Add full image preallocation opti
From: |
Hu Tao |
Subject: |
[Qemu-devel] [RFC PATCH v4 4/4] qcow2: Add full image preallocation option |
Date: |
Fri, 27 Dec 2013 11:05:54 +0800 |
This adds a preallocation=full mode to qcow2 image creation, which
creates a non-sparse image file.
Signed-off-by: Hu Tao <address@hidden>
---
block/qcow2.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index f0a8d87..f601089 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1448,6 +1448,7 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
QEMUOptionParameter *options, int version,
Error **errp)
{
+ QEMUOptionParameter *alloc_options = NULL;
/* Calculate cluster_bits */
int cluster_bits;
cluster_bits = ffs(cluster_size) - 1;
@@ -1477,16 +1478,53 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
Error *local_err = NULL;
int ret;
+ if (prealloc == PREALLOC_MODE_FULL) {
+ int64_t meta_size = 0;
+ unsigned nrefe, nl2e;
+ BlockDriver *drv;
+
+ drv = bdrv_find_protocol(filename, true);
+ if (drv == NULL) {
+ error_setg(errp, "Could not find protocol for file '%s'",
filename);
+ return -ENOENT;
+ }
+
+ alloc_options = append_option_parameters(alloc_options,
+ drv->create_options);
+ alloc_options = append_option_parameters(alloc_options, options);
+
+ /* header: 1 cluster */
+ meta_size += cluster_size;
+ /* total size of refblocks */
+ nrefe = (total_size / cluster_size);
+ nrefe = align_offset(nrefe, cluster_size / sizeof(uint16_t));
+ meta_size += nrefe * sizeof(uint16_t);
+ /* total size of reftables */
+ meta_size += nrefe * sizeof(uint16_t) * sizeof(uint16_t) /
cluster_size;
+ /* total size of L2 tables */
+ nl2e = total_size / cluster_size;
+ nl2e = align_offset(nl2e, cluster_size / sizeof(uint64_t));
+ meta_size += nl2e * sizeof(uint64_t);
+ /* total size of L1 tables */
+ meta_size += nl2e * sizeof(uint64_t) * sizeof(uint64_t) / cluster_size;
+
+ set_option_parameter_int(alloc_options, BLOCK_OPT_SIZE,
+ total_size + meta_size);
+ set_option_parameter(alloc_options, BLOCK_OPT_PREALLOC, "full");
+
+ options = alloc_options;
+ }
+
ret = bdrv_create_file(filename, options, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
- return ret;
+ goto out_options;
}
ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
- return ret;
+ goto out_options;
}
/* Write the header */
@@ -1603,6 +1641,8 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
ret = 0;
out:
bdrv_unref(bs);
+out_options:
+ free_option_parameters(alloc_options);
return ret;
}
@@ -1638,6 +1678,8 @@ static int qcow2_create(const char *filename,
QEMUOptionParameter *options,
prealloc = PREALLOC_MODE_OFF;
} else if (!strcmp(options->value.s, "metadata")) {
prealloc = PREALLOC_MODE_METADATA;
+ } else if (!strcmp(options->value.s, "full")) {
+ prealloc = PREALLOC_MODE_FULL;
} else {
error_setg(errp, "Invalid preallocation mode: '%s'",
options->value.s);
@@ -2223,7 +2265,7 @@ static QEMUOptionParameter qcow2_create_options[] = {
{
.name = BLOCK_OPT_PREALLOC,
.type = OPT_STRING,
- .help = "Preallocation mode (allowed values: off, metadata)"
+ .help = "Preallocation mode (allowed values: off, metadata, full)"
},
{
.name = BLOCK_OPT_LAZY_REFCOUNTS,
--
1.7.11.7