From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, stefanha@redhat.com
Subject: [Qemu-devel] [PATCH v2 21/21] qcow2: Gather clusters in a looping loop
Date: Tue, 26 Mar 2013 17:50:13 +0100 [thread overview]
Message-ID: <1364316613-31223-22-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1364316613-31223-1-git-send-email-kwolf@redhat.com>
Instead of just checking once in exactly this order if there are
dependendies, non-COW clusters and new allocation, this starts looping
around these. This way we can, for example, gather non-COW clusters after
new allocations as long as the host cluster offsets stay contiguous.
Once handle_dependencies() is extended so that COW areas of in-flight
allocations can be overwritten, this allows to continue with gathering
other clusters (we wouldn't be able to do that without this change
because we would have missed a possible second dependency in one of the
next clusters).
This means that in the typical sequential write case, we can combine the
COW overwrite of one cluster with the allocation of the next cluster as
soon as something like Delayed COW gets actually implemented. It is only
by avoiding splitting requests this way that Delayed COW actually starts
improving performance noticably.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2-cluster.c | 72 ++++++++++++++++++++++++++--------------------
tests/qemu-iotests/044.out | 2 +-
2 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 960d446..7208810 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -770,7 +770,7 @@ out:
* must start over anyway, so consider *cur_bytes undefined.
*/
static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
- uint64_t *cur_bytes)
+ uint64_t *cur_bytes, QCowL2Meta **m)
{
BDRVQcowState *s = bs->opaque;
QCowL2Meta *old_alloc;
@@ -793,6 +793,13 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
bytes = 0;
}
+ /* Stop if already an l2meta exists. We would have to consider
+ * locks held by it (l2_writeback_lock) and set m->next etc. */
+ if (bytes == 0 && *m) {
+ *cur_bytes = 0;
+ return 0;
+ }
+
if (bytes == 0) {
/* Wait for the dependency to complete. We need to recheck
* the free/allocated clusters when we continue. */
@@ -1023,16 +1030,16 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
}
+ /* This function is only called when there were no non-COW clusters, so if
+ * we can't find any unallocated or COW clusters either, something is
+ * wrong with our code. */
+ assert(nb_clusters > 0);
+
ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
if (ret < 0) {
return ret;
}
- if (nb_clusters == 0) {
- *bytes = 0;
- return 0;
- }
-
/* Allocate, if necessary at a given offset in the image file */
alloc_cluster_offset = start_of_cluster(s, *host_offset);
ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
@@ -1146,8 +1153,27 @@ again:
remaining = (n_end - n_start) << BDRV_SECTOR_BITS;
cluster_offset = 0;
*host_offset = 0;
+ cur_bytes = 0;
+ *m = NULL;
while (true) {
+
+ if (!*host_offset) {
+ *host_offset = start_of_cluster(s, cluster_offset);
+ }
+
+ assert(remaining >= cur_bytes);
+
+ start += cur_bytes;
+ remaining -= cur_bytes;
+ cluster_offset += cur_bytes;
+
+ if (remaining == 0) {
+ break;
+ }
+
+ cur_bytes = remaining;
+
/*
* Now start gathering as many contiguous clusters as possible:
*
@@ -1166,12 +1192,17 @@ again:
* the right synchronisation between the in-flight request and
* the new one.
*/
- cur_bytes = remaining;
- ret = handle_dependencies(bs, start, &cur_bytes);
+ ret = handle_dependencies(bs, start, &cur_bytes, m);
if (ret == -EAGAIN) {
+ /* Currently handle_dependencies() doesn't yield if we already had
+ * an allocation. If it did, we would have to clean up the L2Meta
+ * structs before starting over. */
+ assert(*m == NULL);
goto again;
} else if (ret < 0) {
return ret;
+ } else if (cur_bytes == 0) {
+ break;
} else {
/* handle_dependencies() may have decreased cur_bytes (shortened
* the allocations below) so that the next dependency is processed
@@ -1185,24 +1216,11 @@ again:
if (ret < 0) {
return ret;
} else if (ret) {
- if (!*host_offset) {
- *host_offset = start_of_cluster(s, cluster_offset);
- }
-
- start += cur_bytes;
- remaining -= cur_bytes;
- cluster_offset += cur_bytes;
-
- cur_bytes = remaining;
+ continue;
} else if (cur_bytes == 0) {
break;
}
- /* If there is something left to allocate, do that now */
- if (remaining == 0) {
- break;
- }
-
/*
* 3. If the request still hasn't completed, allocate new clusters,
* considering any cluster_offset of steps 1c or 2.
@@ -1211,15 +1229,7 @@ again:
if (ret < 0) {
return ret;
} else if (ret) {
- if (!*host_offset) {
- *host_offset = start_of_cluster(s, cluster_offset);
- }
-
- start += cur_bytes;
- remaining -= cur_bytes;
- cluster_offset += cur_bytes;
-
- break;
+ continue;
} else {
assert(cur_bytes == 0);
break;
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
index 34c25c7..5c5aa92 100644
--- a/tests/qemu-iotests/044.out
+++ b/tests/qemu-iotests/044.out
@@ -1,6 +1,6 @@
No errors were found on the image.
7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters
-Image end offset: 4296447488
+Image end offset: 4296448000
.
----------------------------------------------------------------------
Ran 1 tests
--
1.8.1.4
next prev parent reply other threads:[~2013-03-26 16:50 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-26 16:49 [Qemu-devel] [PATCH v2 00/21] qcow2: Rework cluster allocation even more Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 01/21] qemu-iotests: More concurrent allocation scenarios Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 02/21] qcow2: Fix "total clusters" number in bdrv_check Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 03/21] qcow2: Remove bogus unlock of s->lock Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 04/21] qcow2: Handle dependencies earlier Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 05/21] qcow2: Improve check for overlapping allocations Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 06/21] qcow2: Change handle_dependency to byte granularity Kevin Wolf
2013-03-26 16:49 ` [Qemu-devel] [PATCH v2 07/21] qcow2: Decouple cluster allocation from cluster reuse code Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 08/21] qcow2: Factor out handle_alloc() Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 09/21] qcow2: handle_alloc(): Get rid of nb_clusters parameter Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 10/21] qcow2: handle_alloc(): Get rid of keep_clusters parameter Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 11/21] qcow2: Finalise interface of handle_alloc() Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 12/21] qcow2: Clean up handle_alloc() Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 13/21] qcow2: Factor out handle_copied() Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 14/21] qcow2: handle_copied(): Get rid of nb_clusters parameter Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 15/21] qcow2: handle_copied(): Get rid of keep_clusters parameter Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 16/21] qcow2: handle_copied(): Implement non-zero host_offset Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 17/21] qcow2: Prepare handle_alloc/copied() for byte granularity Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 18/21] qcow2: Use byte granularity in qcow2_alloc_cluster_offset() Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 19/21] qcow2: Allow requests with multiple l2metas Kevin Wolf
2013-03-26 16:50 ` [Qemu-devel] [PATCH v2 20/21] qcow2: Move cluster gathering to a non-looping loop Kevin Wolf
2013-03-26 16:50 ` Kevin Wolf [this message]
2013-03-27 10:27 ` [Qemu-devel] [PATCH v2 21/21] qcow2: Gather clusters in a looping loop Stefan Hajnoczi
2013-03-27 10:43 ` [Qemu-devel] [PATCH v3 " Kevin Wolf
2013-03-27 10:29 ` [Qemu-devel] [PATCH v2 00/21] qcow2: Rework cluster allocation even more Stefan Hajnoczi
2013-03-27 12:41 ` Stefan Hajnoczi
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=1364316613-31223-22-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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).