summaryrefslogtreecommitdiff
path: root/block/qcow2.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2012-12-07 18:08:46 +0100
committerKevin Wolf <kwolf@redhat.com>2012-12-13 15:37:59 +0100
commitf50f88b9fea09fef12cc293126cf45dcf0ef600b (patch)
tree2060b173e0069405cca56846cce4fe44e793952c /block/qcow2.c
parent060bee8943c27d4d53f65570fafaa2559fcd87c3 (diff)
downloadqemu-f50f88b9fea09fef12cc293126cf45dcf0ef600b.tar.gz
qcow2: Allocate l2meta only for cluster allocations
Even for writes to already allocated clusters, an l2meta is allocated, though it stays effectively unused. After this patch, only allocating requests still have one. Each l2meta now describes an in-flight request that writes to clusters that are not yet hooked up in the L2 table. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/qcow2.c')
-rw-r--r--block/qcow2.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/block/qcow2.c b/block/qcow2.c
index 66ca12f94e..08d92cc6e3 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -787,8 +787,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
while (remaining_sectors != 0) {
- l2meta = g_malloc0(sizeof(*l2meta));
- qemu_co_queue_init(&l2meta->dependent_requests);
+ l2meta = NULL;
trace_qcow2_writev_start_part(qemu_coroutine_self());
index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -799,7 +798,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
}
ret = qcow2_alloc_cluster_offset(bs, sector_num << 9,
- index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, l2meta);
+ index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, &l2meta);
if (ret < 0) {
goto fail;
}
@@ -845,14 +844,16 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
goto fail;
}
- ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
- if (ret < 0) {
- goto fail;
- }
+ if (l2meta != NULL) {
+ ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
+ if (ret < 0) {
+ goto fail;
+ }
- run_dependent_requests(s, l2meta);
- g_free(l2meta);
- l2meta = NULL;
+ run_dependent_requests(s, l2meta);
+ g_free(l2meta);
+ l2meta = NULL;
+ }
remaining_sectors -= cur_nr_sectors;
sector_num += cur_nr_sectors;
@@ -1134,11 +1135,10 @@ static int preallocate(BlockDriverState *bs)
uint64_t host_offset = 0;
int num;
int ret;
- QCowL2Meta meta;
+ QCowL2Meta *meta;
nb_sectors = bdrv_getlength(bs) >> 9;
offset = 0;
- qemu_co_queue_init(&meta.dependent_requests);
while (nb_sectors) {
num = MIN(nb_sectors, INT_MAX >> 9);
@@ -1148,15 +1148,17 @@ static int preallocate(BlockDriverState *bs)
return ret;
}
- ret = qcow2_alloc_cluster_link_l2(bs, &meta);
+ ret = qcow2_alloc_cluster_link_l2(bs, meta);
if (ret < 0) {
- qcow2_free_any_clusters(bs, meta.alloc_offset, meta.nb_clusters);
+ qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters);
return ret;
}
/* There are no dependent requests, but we need to remove our request
* from the list of in-flight requests */
- run_dependent_requests(bs->opaque, &meta);
+ if (meta != NULL) {
+ run_dependent_requests(bs->opaque, meta);
+ }
/* TODO Preallocate data if requested */