From 0b919fae31f4f80f78ebeab8388dc3a03cc5e4ed Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 19 Jun 2013 13:44:20 +0200 Subject: qcow2: Batch discards This optimises the discard operation for freed clusters by batching discard requests (both snapshot deletion and bdrv_discard end up updating the refcounts cluster by cluster). Note that we don't discard asynchronously, but keep s->lock held. This is to avoid that a freed cluster is reallocated and written to while the discard is still in flight. Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- block/qcow2-cluster.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'block/qcow2-cluster.c') diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 3191d6b3e6..cca76d4fcd 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1377,18 +1377,25 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, nb_clusters = size_to_clusters(s, end_offset - offset); + s->cache_discards = true; + /* Each L2 table is handled by its own loop iteration */ while (nb_clusters > 0) { ret = discard_single_l2(bs, offset, nb_clusters); if (ret < 0) { - return ret; + goto fail; } nb_clusters -= ret; offset += (ret * s->cluster_size); } - return 0; + ret = 0; +fail: + s->cache_discards = false; + qcow2_process_discards(bs, ret); + + return ret; } /* @@ -1450,15 +1457,22 @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors) /* Each L2 table is handled by its own loop iteration */ nb_clusters = size_to_clusters(s, nb_sectors << BDRV_SECTOR_BITS); + s->cache_discards = true; + while (nb_clusters > 0) { ret = zero_single_l2(bs, offset, nb_clusters); if (ret < 0) { - return ret; + goto fail; } nb_clusters -= ret; offset += (ret * s->cluster_size); } - return 0; + ret = 0; +fail: + s->cache_discards = false; + qcow2_process_discards(bs, ret); + + return ret; } -- cgit v1.2.1