From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:51268) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TOW4X-00056C-OD for qemu-devel@nongnu.org; Wed, 17 Oct 2012 12:02:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TOW4N-0003Ko-6D for qemu-devel@nongnu.org; Wed, 17 Oct 2012 12:02:17 -0400 Received: from nodalink.pck.nerim.net ([62.212.105.220]:48821 helo=paradis.irqsave.net) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TOW4M-0003Ji-Hs for qemu-devel@nongnu.org; Wed, 17 Oct 2012 12:02:07 -0400 From: =?UTF-8?q?Beno=C3=AEt=20Canet?= Date: Wed, 17 Oct 2012 18:00:26 +0200 Message-Id: <1350489629-1838-18-git-send-email-benoit@irqsave.net> In-Reply-To: <1350489629-1838-1-git-send-email-benoit@irqsave.net> References: <1350489629-1838-1-git-send-email-benoit@irqsave.net> Subject: [Qemu-devel] [RFC V2 17/20] qcow2: Integrate deduplication in qcow2_co_writev loop. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, =?UTF-8?q?Beno=C3=AEt=20Canet?= , stefanha@redhat.com --- block/qcow2.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index c6879ea..e0c1a68 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -330,6 +330,7 @@ static int qcow2_open(BlockDriverState *bs, int flags) QCowHeader header; uint64_t ext_end; + s->has_dedup = false; ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); if (ret < 0) { goto fail; @@ -812,6 +813,12 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, QEMUIOVector hd_qiov; uint64_t bytes_done = 0; uint8_t *cluster_data = NULL; + uint8_t *dedup_cluster_data = NULL; + uint8_t *next_call_first_hash; + int dedup_cluster_data_nr; + int deduped_sectors_nr; + int skip_before_dedup_clusters_nr; + int next_non_dedupable_sectors_nr; QCowL2Meta l2meta = { .nb_clusters = 0, }; @@ -827,11 +834,66 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, qemu_co_mutex_lock(&s->lock); + if (s->has_dedup) { + /* if deduplication is on we make sure dedup_cluster_data + * contains a multiple of cluster size of data in order + * to compute the hashes + */ + ret = qcow2_dedup_read_missing_and_concatenate(bs, + qiov, + sector_num, + remaining_sectors, + &dedup_cluster_data, + &dedup_cluster_data_nr); + + if (ret < 0) { + goto fail; + } + } + + next_call_first_hash = NULL; + next_non_dedupable_sectors_nr = 0; + skip_before_dedup_clusters_nr = 0; while (remaining_sectors != 0) { trace_qcow2_writev_start_part(qemu_coroutine_self()); + + if (s->has_dedup && next_non_dedupable_sectors_nr == 0) { + /* Try to deduplicate as much clusters as possible */ + deduped_sectors_nr = qcow2_dedup(bs, + sector_num, + dedup_cluster_data, + dedup_cluster_data_nr, + &skip_before_dedup_clusters_nr, + &next_non_dedupable_sectors_nr, + &next_call_first_hash); + + remaining_sectors -= deduped_sectors_nr; + sector_num += deduped_sectors_nr; + bytes_done += deduped_sectors_nr * 512; + + /* no more data to write -> exit + * Can be < 0 because of the presence of sectors we read in + * qcow2_read_missing_dedup_sectors_and_concatenate. + */ + if (next_non_dedupable_sectors_nr <= 0) { + goto fail; + } + + /* if we deduped something trace it */ + if (deduped_sectors_nr) { + trace_qcow2_writev_done_part(qemu_coroutine_self(), + deduped_sectors_nr); + trace_qcow2_writev_start_part(qemu_coroutine_self()); + } + } + index_in_cluster = sector_num & (s->cluster_sectors - 1); - n_end = index_in_cluster + remaining_sectors; + n_end = s->has_dedup && + next_non_dedupable_sectors_nr < remaining_sectors ? + index_in_cluster + next_non_dedupable_sectors_nr : + index_in_cluster + remaining_sectors; + if (s->crypt_method && n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) { n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; @@ -873,6 +935,19 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, cur_nr_sectors * 512); } + /* Write the non duplicated clusters hashes to disk + * just before writing non duplicated data. + */ + if (s->has_dedup) { + ret = qcow2_dedup_write_new_hashes(bs, + (cluster_offset >> 9), + cur_nr_sectors / + s->cluster_sectors); + if (ret < 0) { + goto fail; + } + } + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); qemu_co_mutex_unlock(&s->lock); trace_qcow2_writev_data(qemu_coroutine_self(), @@ -892,6 +967,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, run_dependent_requests(s, &l2meta); + next_non_dedupable_sectors_nr -= cur_nr_sectors; remaining_sectors -= cur_nr_sectors; sector_num += cur_nr_sectors; bytes_done += cur_nr_sectors * 512; @@ -906,6 +982,7 @@ fail: qemu_iovec_destroy(&hd_qiov); qemu_vfree(cluster_data); + qemu_vfree(dedup_cluster_data); trace_qcow2_writev_done_req(qemu_coroutine_self(), ret); return ret; -- 1.7.10.4