[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC V3 16/24] qcow2: Allow creation of images using dedupl
From: |
Benoît Canet |
Subject: |
[Qemu-devel] [RFC V3 16/24] qcow2: Allow creation of images using deduplication. |
Date: |
Mon, 26 Nov 2012 14:05:15 +0100 |
todo: Change qemu-img output so it reflect the dedup cluster size.
Signed-off-by: Benoit Canet <address@hidden>
---
block/qcow2.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++--------
block/qcow2.h | 2 ++
2 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 76d2340..e641049 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -277,6 +277,11 @@ static int qcow2_mark_dirty(BlockDriverState *bs)
return qcow2_add_feature(bs, QCOW2_INCOMPAT_DIRTY);
}
+static int qcow2_activate_dedup(BlockDriverState *bs)
+{
+ return qcow2_add_feature(bs, QCOW2_INCOMPAT_DEDUP);
+}
+
/*
* Clears an incompatible feature bit and flushes before if necessary.
* Only call this function when there are no pending requests, it does not
@@ -913,6 +918,11 @@ static void qcow2_close(BlockDriverState *bs)
BDRVQcowState *s = bs->opaque;
g_free(s->l1_table);
+ if (s->has_dedup) {
+ qcow2_cache_flush(bs, s->dedup_cluster_cache);
+ qcow2_cache_destroy(bs, s->dedup_cluster_cache);
+ }
+
qcow2_cache_flush(bs, s->l2_table_cache);
qcow2_cache_flush(bs, s->refcount_block_cache);
@@ -1231,7 +1241,8 @@ static int preallocate(BlockDriverState *bs)
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, int prealloc,
- QEMUOptionParameter *options, int version)
+ QEMUOptionParameter *options, int version,
+ bool dedup)
{
/* Calculate cluster_bits */
int cluster_bits;
@@ -1258,8 +1269,10 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
* size for any qcow2 image.
*/
BlockDriverState* bs;
+ BDRVQcowState *s;
QCowHeader header;
- uint8_t* refcount_table;
+ uint8_t *tables;
+ int size;
int ret;
ret = bdrv_create_file(filename, options);
@@ -1301,10 +1314,11 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
goto out;
}
- /* Write an empty refcount table */
- refcount_table = g_malloc0(cluster_size);
- ret = bdrv_pwrite(bs, cluster_size, refcount_table, cluster_size);
- g_free(refcount_table);
+ /* Write an empty refcount table + extra space for dedup table if needed */
+ size = cluster_size * (dedup ? 2 : 1);
+ tables = g_malloc0(size);
+ ret = bdrv_pwrite(bs, cluster_size, tables, size);
+ g_free(tables);
if (ret < 0) {
goto out;
@@ -1325,7 +1339,8 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
goto out;
}
- ret = qcow2_alloc_clusters(bs, 2 * cluster_size);
+ size += cluster_size;
+ ret = qcow2_alloc_clusters(bs, size);
if (ret < 0) {
goto out;
@@ -1335,11 +1350,32 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
}
/* Okay, now that we have a valid image, let's give it the right size */
+ s = bs->opaque;
+ size = (total_size + (dedup ? s->cluster_sectors : 0)) * BDRV_SECTOR_SIZE;
ret = bdrv_truncate(bs, total_size * BDRV_SECTOR_SIZE);
if (ret < 0) {
goto out;
}
+ if (dedup) {
+ s->has_dedup = true;
+ s->dedup_table_offset = cluster_size * 2;
+ s->dedup_table_size = cluster_size / sizeof(uint64_t);
+
+ ret = qcow2_activate_dedup(bs);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = qcow2_update_header(bs);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* minimal init */
+ s->dedup_cluster_cache = qcow2_cache_create(bs, DEDUP_CACHE_SIZE);
+ }
+
/* Want a backing file? There you go.*/
if (backing_file) {
ret = bdrv_change_backing_file(bs, backing_file, backing_format);
@@ -1365,15 +1401,30 @@ out:
return ret;
}
+static int qcow2_warn_if_version_3_is_needed(int version,
+ bool has_feature,
+ const char *feature)
+{
+ if (version < 3 && has_feature) {
+ fprintf(stderr, "%s only supported with compatibility "
+ "level 1.1 and above (use compat=1.1 or greater)\n",
+ feature);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int qcow2_create(const char *filename, QEMUOptionParameter *options)
{
const char *backing_file = NULL;
const char *backing_fmt = NULL;
uint64_t sectors = 0;
int flags = 0;
+ int ret;
size_t cluster_size = DEFAULT_CLUSTER_SIZE;
int prealloc = 0;
int version = 2;
+ bool dedup = false;
/* Read out options */
while (options && options->name) {
@@ -1411,24 +1462,38 @@ static int qcow2_create(const char *filename,
QEMUOptionParameter *options)
}
} else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0;
+ } else if (!strcmp(options->name, BLOCK_OPT_DEDUP)) {
+ dedup = options->value.n ? true : false;
}
options++;
}
+ if (dedup) {
+ cluster_size = 4096;
+ }
+
if (backing_file && prealloc) {
fprintf(stderr, "Backing file and preallocation cannot be used at "
"the same time\n");
return -EINVAL;
}
- if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) {
- fprintf(stderr, "Lazy refcounts only supported with compatibility "
- "level 1.1 and above (use compat=1.1 or greater)\n");
- return -EINVAL;
+ ret = qcow2_warn_if_version_3_is_needed(version,
+ flags & BLOCK_FLAG_LAZY_REFCOUNTS,
+ "Lazy refcounts");
+ if (ret < 0) {
+ return ret;
+ }
+ ret = qcow2_warn_if_version_3_is_needed(version,
+ dedup,
+ "Deduplication");
+ if (ret < 0) {
+ return ret;
}
return qcow2_create2(filename, sectors, backing_file, backing_fmt, flags,
- cluster_size, prealloc, options, version);
+ cluster_size, prealloc, options, version,
+ dedup);
}
static int qcow2_make_empty(BlockDriverState *bs)
@@ -1731,6 +1796,11 @@ static QEMUOptionParameter qcow2_create_options[] = {
.type = OPT_FLAG,
.help = "Postpone refcount updates",
},
+ {
+ .name = BLOCK_OPT_DEDUP,
+ .type = OPT_FLAG,
+ .help = "Live deduplication",
+ },
{ NULL }
};
diff --git a/block/qcow2.h b/block/qcow2.h
index 9d08bf9..90dcdd9 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -56,6 +56,8 @@
/* Must be at least 4 to cover all cases of refcount table growth */
#define REFCOUNT_CACHE_SIZE 4
+#define DEDUP_CACHE_SIZE 4
+
#define DEFAULT_CLUSTER_SIZE 65536
/* indicate that the hash structure is empty and miss offset */
--
1.7.10.4
- [Qemu-devel] [RFC V3 01/24] qcow2: Add deduplication to the qcow2 specification., (continued)
- [Qemu-devel] [RFC V3 01/24] qcow2: Add deduplication to the qcow2 specification., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 04/24] qcow2: Make update_cluster_refcount public., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 05/24] qcow2: Create a way to link to l2 tables in dedup., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 03/24] qcow2: Add qcow2_de dup_read_missing_and_concatenate, Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 06/24] qcow2: Add qcow2_dedup and related functions., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 09/24] qcow2: Extract qcow2_dedup_grow_table, Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 13/24] qcow2: Add qcow2_dedup_init and qcow2_dedup_close., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 12/24] qcow2: Extract qcow2_do_table_init., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 11/24] qcow2: Load and save deduplication table header extension., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 14/24] qcow2: Extract qcow2_add_feature and qcow2_remove_feature., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 16/24] qcow2: Allow creation of images using deduplication.,
Benoît Canet <=
- [Qemu-devel] [RFC V3 17/24] qcow2: Behave correctly when refcount reach 0 or 2^16., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 19/24] qcow2: Add verification of dedup table., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 24/24] qemu-iotests: Filter dedup=on/off so existing tests don't break., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 20/24] qcow2: Adapt checking of QCOW_OFLAG_COPIED for dedup., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 22/24] qcow2: Do not overwrite existing entries with QCOW_OFLAG_COPIED., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 07/24] qcow2: Add qcow2_dedup_write_new_hashes., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 18/24] qcow2: Integrate deduplication in qcow2_co_writev loop., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 08/24] qcow2: Implement qcow2_compute_cluster_hash., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 21/24] qcow2: Add check_dedup_l2 in order to check l2 of dedup table., Benoît Canet, 2012/11/26
- [Qemu-devel] [RFC V3 23/24] qcow2: init and cleanup deduplication., Benoît Canet, 2012/11/26