[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH v2 23/23] qcow2: Gather clusters in a looping lo
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [RFC PATCH v2 23/23] qcow2: Gather clusters in a looping loop |
Date: |
Wed, 13 Feb 2013 14:22:13 +0100 |
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.
More importantly, after overwriting a COW in handle_dependencies() we
can now continue with gathering other clusters (we couldn't do that
before because we would miss 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.
Only by avoiding splitting requests this way Delayed COW actually starts
improving performance noticably.
Signed-off-by: Kevin Wolf <address@hidden>
---
block/qcow2-cluster.c | 66 ++++++++++++++++++++++--------------------------
1 files changed, 30 insertions(+), 36 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 5a97d87..34f7299 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1209,16 +1209,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 = *host_offset;
ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
@@ -1334,9 +1334,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:
*
@@ -1355,20 +1373,17 @@ again:
* the right synchronisation between the in-flight request and
* the new one.
*/
- cur_bytes = remaining;
ret = handle_dependencies(bs, start, &cluster_offset, &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 (ret) {
- *host_offset = start_of_cluster(s, cluster_offset);
-
- start += cur_bytes;
- remaining -= cur_bytes;
- cluster_offset += cur_bytes;
-
- break;
+ continue;
} else if (cur_bytes == 0) {
break;
} else {
@@ -1384,24 +1399,11 @@ again:
if (ret < 0) {
return ret;
} else if (ret) {
- if (!*host_offset) {
- *host_offset = 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.
@@ -1410,15 +1412,7 @@ again:
if (ret < 0) {
return ret;
} else if (ret) {
- if (!*host_offset) {
- *host_offset = cluster_offset;
- }
-
- start += cur_bytes;
- remaining -= cur_bytes;
- cluster_offset += cur_bytes;
-
- break;
+ continue;
} else {
assert(cur_bytes == 0);
break;
--
1.7.6.5
- [Qemu-devel] [RFC PATCH v2 14/23] qcow2: Use byte granularity in qcow2_alloc_cluster_offset(), (continued)
- [Qemu-devel] [RFC PATCH v2 14/23] qcow2: Use byte granularity in qcow2_alloc_cluster_offset(), Kevin Wolf, 2013/02/13
- [Qemu-devel] [RFC PATCH v2 17/23] qcow2: Move COW and L2 update into own coroutine, Kevin Wolf, 2013/02/13
- [Qemu-devel] [RFC PATCH v2 22/23] qcow2: Move cluster gathering to a non-looping loop, Kevin Wolf, 2013/02/13
- [Qemu-devel] [RFC PATCH v2 21/23] qemu-iotests: Another concurrent multicluster allocation case, Kevin Wolf, 2013/02/13
- [Qemu-devel] [RFC PATCH v2 20/23] qcow2: Cancel COW when overwritten, Kevin Wolf, 2013/02/13
- [Qemu-devel] [RFC PATCH v2 23/23] qcow2: Gather clusters in a looping loop,
Kevin Wolf <=
- Re: [Qemu-devel] [RFC PATCH v2 00/23] qcow2: Delayed COW, Stefan Hajnoczi, 2013/02/14
- Re: [Qemu-devel] [RFC PATCH v2 00/23] qcow2: Delayed COW, Stefan Hajnoczi, 2013/02/18