From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:44871) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QmQyg-000276-6U for qemu-devel@nongnu.org; Thu, 28 Jul 2011 09:50:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QmQye-0002D3-Ps for qemu-devel@nongnu.org; Thu, 28 Jul 2011 09:50:18 -0400 Received: from mail-fx0-f45.google.com ([209.85.161.45]:42482) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QmQye-0002Cu-H8 for qemu-devel@nongnu.org; Thu, 28 Jul 2011 09:50:16 -0400 Received: by fxbb27 with SMTP id b27so1065415fxb.4 for ; Thu, 28 Jul 2011 06:50:15 -0700 (PDT) From: Frediano Ziglio Date: Thu, 28 Jul 2011 15:50:17 +0200 Message-Id: <1311861017-13425-1-git-send-email-freddy77@gmail.com> Subject: [Qemu-devel] [PATCH] [RFC] qcow2: group refcount updates during cow List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Kevin Wolf Cc: qemu-devel@nongnu.org, Frediano Ziglio Well, I think this is the first real improve patch. Is more a RFC than a patch. Yes, some lines are terrible! It collapses refcount decrement during cow. >>From a first check time executing 015 test passed from about 600 seconds to 70. This at least prove that refcount updates counts! Some doubt: 1- place the code in qcow2-refcount.c as it update only refcount and not cluster? 2- allow some sort of "begin transaction" / "commit" / "rollback" like databases instead? 3- allow changing tables from different coroutines? 1) If you have a sequence like (1, 2, 4) probably these clusters are all in the same l2 table but with this code you get two write instead of one. I'm thinking about a function in qcow2-refcount.c that accept an array of cluster instead of a start + len. Signed-off-by: Frediano Ziglio --- block/qcow2-cluster.c | 36 ++++++++++++++++++++++++++++++++++-- 1 files changed, 34 insertions(+), 2 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 81cf77d..da17365 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -675,10 +675,42 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) * Also flush bs->file to get the right order for L2 and refcount update. */ if (j != 0) { + int64_t old_start = 0, old_end = -2; + int count = 0; for (i = 0; i < j; i++) { - qcow2_free_any_clusters(bs, - be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1); + old_cluster[i] = be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED; } + // XXX sort old_cluster + for (i = 0; i < j; i++) { + int64_t cluster = old_cluster[i]; + + /* group if contiguos */ + if (old_end + 1 == (cluster >> s->cluster_bits)) { + ++old_end; + continue; + } + + /* handle */ + if (old_end > 0) { + qcow2_free_any_clusters(bs, old_start << s->cluster_bits, old_end - old_start + 1); + count += old_end - old_start + 1; + } + old_end = -2; + + /* handle compressed separately */ + if ((cluster & QCOW_OFLAG_COMPRESSED)) { + qcow2_free_any_clusters(bs, cluster, 1); + continue; + } + + /* start a new group */ + old_start = old_end = cluster >> s->cluster_bits; + } + if (old_end > 0) { + qcow2_free_any_clusters(bs, old_start << s->cluster_bits, old_end - old_start + 1); + count += old_end - old_start + 1; + } + assert(count == j); } ret = 0; -- 1.7.1