[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC V7 31/32] qcow2: Add qcow2_co_dedup_resume to restart
From: |
Benoît Canet |
Subject: |
[Qemu-devel] [RFC V7 31/32] qcow2: Add qcow2_co_dedup_resume to restart deduplication. |
Date: |
Fri, 15 Mar 2013 15:49:45 +0100 |
---
block/qcow2-dedup.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 179 insertions(+)
diff --git a/block/qcow2-dedup.c b/block/qcow2-dedup.c
index c2dd145..93917d5 100644
--- a/block/qcow2-dedup.c
+++ b/block/qcow2-dedup.c
@@ -37,6 +37,7 @@
#include <skeinApi.h>
#endif
+static void qcow2_dedup_reset(BlockDriverState *bs);
static int qcow2_dedup_read_write_hash(BlockDriverState *bs,
QCowHash *hash,
uint64_t *first_logical_sect,
@@ -1092,6 +1093,174 @@ bool qcow2_dedup_is_running(BlockDriverState *bs)
return s->has_dedup && s->dedup_status == DEDUP_STATUS_STARTED;
}
+static bool hash_is_null(QCowHash *hash)
+{
+ QCowHash null_hash;
+ memset(&null_hash.data, 0, HASH_LENGTH);
+ return !memcmp(hash->data, null_hash.data, HASH_LENGTH);
+}
+
+static void qcow2_dedup_insert_hash_node(BlockDriverState *bs,
+ QCowHashNode *hash_node)
+{
+ BDRVQcowState *s = bs->opaque;
+
+ g_tree_insert(s->dedup_tree_by_hash, &hash_node->hash, hash_node);
+}
+
+/* This load the QCowHashNode corresponding to a given cluster index into ram
+ *
+ * @index: index of the given physical sector
+ * @ret: 0 on succes, negative on error
+ */
+static int qcow2_load_cluster_hash(BlockDriverState *bs,
+ uint64_t index)
+{
+ BDRVQcowState *s = bs->opaque;
+ int ret = 0;
+ QCowHash hash;
+ uint64_t first_logical_sect;
+ QCowHashNode *hash_node;
+
+ /* get the hash */
+ ret = qcow2_dedup_read_write_hash(bs, &hash,
+ &first_logical_sect,
+ index * s->cluster_sectors,
+ false);
+
+ if (ret < 0) {
+ error_report("Failed to load deduplication hash.");
+ return ret;
+ }
+
+ /* if the hash is null don't load it */
+ if (hash_is_null(&hash)) {
+ return ret;
+ }
+
+ hash_node = qcow2_hash_node_new(&hash,
+ index * s->cluster_sectors,
+ first_logical_sect);
+ qcow2_dedup_insert_hash_node(bs, hash_node);
+
+ return 0;
+}
+
+/* Load all the actives hashes into RAM
+ *
+ * @ret: 0 on success, negative on error
+ */
+static int qcow2_load_valid_hashes(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint64_t max_clusters, i;
+ int nb_hash_in_hash_block = s->hash_block_size / (HASH_LENGTH + 8);
+ int ret = 0;
+
+ max_clusters = s->dedup_table_size * nb_hash_in_hash_block;
+
+ /* load all the hash stored to disk in memory */
+ for (i = 0; i < max_clusters; i++) {
+ if (!(i % nb_hash_in_hash_block)) {
+ co_sleep_ns(rt_clock, s->dedup_co_delay);
+ }
+ qemu_co_mutex_lock(&s->lock);
+ ret = qcow2_load_cluster_hash(bs, i);
+ qemu_co_mutex_unlock(&s->lock);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int qcow2_drop_to_dedup_stale_hash(BlockDriverState *bs,
+ uint64_t index)
+{
+ int ret = 0;
+ bool to_dedup;
+ uint64_t physical_sect;
+
+ to_dedup = qcow2_is_cluster_to_dedup(bs, index, &physical_sect, &ret);
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (!to_dedup) {
+ return 0;
+ }
+
+ qcow2_remove_hash_node_by_sector(bs, physical_sect);
+ return 0;
+}
+
+/* For each l2 entry marked as QCOW_OFLAG_PENDING_DEDUP drop the obsolete hash
+ * from the trees
+ *
+ * @ret: 0 on success, negative on error
+ */
+static int qcow2_drop_to_dedup_hashes(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint64_t i;
+ int ret = 0;
+
+ /* for each l2 entry */
+ for (i = 0; i < s->l2_size * s->l1_size; i++) {
+ if (!(i % s->l2_size)) {
+ co_sleep_ns(rt_clock, s->dedup_co_delay);
+ }
+ qemu_co_mutex_lock(&s->lock);
+ ret = qcow2_drop_to_dedup_stale_hash(bs, i);
+ qemu_co_mutex_unlock(&s->lock);
+
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * This coroutine resume deduplication
+ *
+ * @data: the given BlockDriverState
+ * @ret: NULL
+ */
+static void coroutine_fn qcow2_co_dedup_resume(void *opaque)
+{
+ BlockDriverState *bs = opaque;
+ BDRVQcowState *s = bs->opaque;
+ int ret = 0;
+
+ ret = qcow2_load_valid_hashes(bs);
+
+ if (ret < 0) {
+ goto fail;
+ }
+
+ ret = qcow2_drop_to_dedup_hashes(bs);
+
+ if (ret < 0) {
+ goto fail;
+ }
+
+ qemu_co_mutex_lock(&s->lock);
+ s->dedup_status = DEDUP_STATUS_STARTED;
+ qemu_co_mutex_unlock(&s->lock);
+
+ return;
+
+fail:
+ qemu_co_mutex_lock(&s->lock);
+ s->dedup_status = DEDUP_STATUS_STOPPED;
+ qcow2_dedup_reset(bs);
+ qemu_co_mutex_unlock(&s->lock);
+}
+
static gint qcow2_dedup_compare_by_hash(gconstpointer a,
gconstpointer b,
gpointer data)
@@ -1142,6 +1311,12 @@ static void qcow2_dedup_free(BlockDriverState *bs)
g_tree_destroy(s->dedup_tree_by_hash);
}
+static void qcow2_dedup_reset(BlockDriverState *bs)
+{
+ qcow2_dedup_free(bs);
+ qcow2_dedup_alloc(bs);
+}
+
int qcow2_dedup_init(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
@@ -1162,6 +1337,10 @@ int qcow2_dedup_init(BlockDriverState *bs)
s->dedup_status = DEDUP_STATUS_STARTING;
+ /* resume deduplication */
+ s->dedup_resume_co = qemu_coroutine_create(qcow2_co_dedup_resume);
+ qemu_coroutine_enter(s->dedup_resume_co, bs);
+
return 0;
}
--
1.7.10.4
- [Qemu-devel] [RFC V7 24/32] qcow2: Serialize write requests when deduplication is activated., (continued)
- [Qemu-devel] [RFC V7 24/32] qcow2: Serialize write requests when deduplication is activated., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 23/32] qcow2: Integrate deduplication in qcow2_co_writev loop., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 19/32] block: Add qcow2_dedup format and image creation code., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 25/32] qcow2: Adapt checking of QCOW_OFLAG_COPIED for dedup., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 26/32] qcow2: Add check_dedup_l2 in order to check l2 of dedup table., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 27/32] qcow2: Add verification of dedup table., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 30/32] qcow2: Add qcow2_dedup_init and qcow2_dedup_close., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 28/32] qcow2: Integrate SKEIN hash algorithm in deduplication., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 29/32] qcow: Set large dedup hash block size., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 32/32] qcow2: Enable the deduplication feature., Benoît Canet, 2013/03/15
- [Qemu-devel] [RFC V7 31/32] qcow2: Add qcow2_co_dedup_resume to restart deduplication.,
Benoît Canet <=