From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>
Subject: [Qemu-devel] [PATCH] qcow2: Cache refcount blocks during snapshot creation
Date: Fri, 26 Jun 2009 20:19:38 +0200 [thread overview]
Message-ID: <1246040378-4134-1-git-send-email-kwolf@redhat.com> (raw)
The really time consuming part of snapshotting is to adjust the reference count
of all clusters. Currently after each adjusted cluster the refcount block is
written to disk.
Don't write each single byte immediately to disk but cache all writes to the
refcount block and write them out once we're done with the block.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2-refcount.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index dd6e293..d42c6e6 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -31,6 +31,26 @@ static int update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length,
int addend);
+
+static int cache_refcount_updates = 0;
+
+static int write_refcount_block(BDRVQcowState *s)
+{
+ size_t size = s->cluster_size;
+
+ if (s->refcount_block_cache_offset == 0) {
+ return 0;
+ }
+
+ if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
+ s->refcount_block_cache, size) != size)
+ {
+ return -EIO;
+ }
+
+ return 0;
+}
+
/*********************************************************/
/* refcount handling */
@@ -68,6 +88,11 @@ static int load_refcount_block(BlockDriverState *bs,
{
BDRVQcowState *s = bs->opaque;
int ret;
+
+ if (cache_refcount_updates) {
+ write_refcount_block(s);
+ }
+
ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
s->cluster_size);
if (ret != s->cluster_size)
@@ -169,6 +194,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
int64_t offset, refcount_block_offset;
int ret, refcount_table_index;
uint64_t data64;
+ int cache = cache_refcount_updates;
/* Find L1 index and grow refcount table if needed */
refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
@@ -181,6 +207,10 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
/* Load or allocate the refcount block */
refcount_block_offset = s->refcount_table[refcount_table_index];
if (!refcount_block_offset) {
+ if (cache_refcount_updates) {
+ write_refcount_block(s);
+ cache_refcount_updates = 0;
+ }
/* create a new refcount block */
/* Note: we cannot update the refcount now to avoid recursion */
offset = alloc_clusters_noref(bs, s->cluster_size);
@@ -199,6 +229,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
refcount_block_offset = offset;
s->refcount_block_cache_offset = offset;
update_refcount(bs, offset, s->cluster_size, 1);
+ cache_refcount_updates = cache;
} else {
if (refcount_block_offset != s->refcount_block_cache_offset) {
if (load_refcount_block(bs, refcount_block_offset) < 0)
@@ -215,6 +246,10 @@ static int write_refcount_block_entries(BDRVQcowState *s,
{
size_t size;
+ if (cache_refcount_updates) {
+ return 0;
+ }
+
first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
last_index = (last_index + REFCOUNTS_PER_SECTOR)
& ~(REFCOUNTS_PER_SECTOR - 1);
@@ -471,6 +506,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
qcow2_l2_cache_reset(bs);
+ cache_refcount_updates = 1;
l2_table = NULL;
l1_table = NULL;
@@ -563,11 +599,15 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
if (l1_allocated)
qemu_free(l1_table);
qemu_free(l2_table);
+ cache_refcount_updates = 0;
+ write_refcount_block(s);
return 0;
fail:
if (l1_allocated)
qemu_free(l1_table);
qemu_free(l2_table);
+ cache_refcount_updates = 0;
+ write_refcount_block(s);
return -EIO;
}
--
1.6.0.6
next reply other threads:[~2009-06-26 18:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-26 18:19 Kevin Wolf [this message]
2009-06-26 18:48 ` [Qemu-devel] [PATCH] qcow2: Cache refcount blocks during snapshot creation Nathan Froyd
2009-06-27 9:01 ` Kevin Wolf
2009-06-27 11:21 ` Stefan Weil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1246040378-4134-1-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).