[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC V2 16/20] qcow2: Allow creation of images using dedupl
From: |
Benoît Canet |
Subject: |
[Qemu-devel] [RFC V2 16/20] qcow2: Allow creation of images using deduplication. |
Date: |
Wed, 17 Oct 2012 18:00:25 +0200 |
todo: Change qemu-img output so it reflect the dedup cluster size.
---
block/qcow2.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
block/qcow2.h | 2 ++
2 files changed, 79 insertions(+), 6 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index b11b6a7..c6879ea 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
@@ -911,6 +916,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);
@@ -1229,7 +1239,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;
@@ -1256,6 +1267,7 @@ 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;
int ret;
@@ -1338,6 +1350,26 @@ static int qcow2_create2(const char *filename, int64_t
total_size,
goto out;
}
+ if (dedup) {
+ s = bs->opaque;
+ s->has_dedup = true;
+ s->dedup_table_offset = qcow2_alloc_clusters(bs, cluster_size);
+ 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);
@@ -1363,15 +1395,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) {
@@ -1409,24 +1456,43 @@ 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 != DEFAULT_CLUSTER_SIZE) {
+ fprintf(stderr, "Deduplication cluster size must be 4096\n");
+ return -EINVAL;
+ }
+
+ 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)
@@ -1729,6 +1795,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 5ecea94..0b999fb 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -57,6 +57,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
/* Red Black Tree deduplication node */
--
1.7.10.4
- [Qemu-devel] [RFC V2 06/20] qcow2: Add qcow2_dedup and related functions., (continued)
- [Qemu-devel] [RFC V2 06/20] qcow2: Add qcow2_dedup and related functions., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 07/20] qcow2: Add qcow2_dedup_write_new_hashes., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 08/20] qcow2: Implement qcow2_compute_cluster_hash., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 09/20] qcow2: Add qcow2_co_load_dedup_hashes., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 05/20] qcow2: Rename update_refcount into qcow2_update_refcount., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 04/20] qcow2: Add qcow2_de dup_read_missing_and_concatenate, Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 15/20] block: Add dedup image create option., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 01/20] qcow2: Add deduplication to the qcow2 specification., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 17/20] qcow2: Integrate deduplication in qcow2_co_writev loop., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 16/20] qcow2: Allow creation of images using deduplication.,
Benoît Canet <=
- [Qemu-devel] [RFC V2 10/20] qcow2: Add qcow2_dedup_grow_table., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 12/20] qcow2: Extract qcow2_do_table_init., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 20/20] qemu-iotests: Filter dedup=on/off so existing tests don't break., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 13/20] qcow2: Add qcow2_dedup_init and qcow2_dedup_close., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 18/20] qcow2: Add method to destroy the deduplication red black tree., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 19/20] qcow2: init and cleanup deduplication., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 02/20] qcow2: Add kernel red black trees, Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 11/20] qcow2: Load and save deduplication table header extension., Benoît Canet, 2012/10/17
- [Qemu-devel] [RFC V2 14/20] qcow2: Extract qcow2_add_feature and qcow2_remove_feature., Benoît Canet, 2012/10/17
- Re: [Qemu-devel] [RFC V2 00/20] QCOW2 deduplication, Avi Kivity, 2012/10/17