Commit 3b88e52b41fe77728b4accb68e14bed98bdc75d3

Authored by Kevin Wolf
Committed by Anthony Liguori
1 parent 22afa7b5

qcow2: Cache refcount blocks during snapshot creation

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>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 1 changed file with 40 additions and 0 deletions
block/qcow2-refcount.c
... ... @@ -31,6 +31,26 @@ static int update_refcount(BlockDriverState *bs,
31 31 int64_t offset, int64_t length,
32 32 int addend);
33 33  
  34 +
  35 +static int cache_refcount_updates = 0;
  36 +
  37 +static int write_refcount_block(BDRVQcowState *s)
  38 +{
  39 + size_t size = s->cluster_size;
  40 +
  41 + if (s->refcount_block_cache_offset == 0) {
  42 + return 0;
  43 + }
  44 +
  45 + if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
  46 + s->refcount_block_cache, size) != size)
  47 + {
  48 + return -EIO;
  49 + }
  50 +
  51 + return 0;
  52 +}
  53 +
34 54 /*********************************************************/
35 55 /* refcount handling */
36 56  
... ... @@ -68,6 +88,11 @@ static int load_refcount_block(BlockDriverState *bs,
68 88 {
69 89 BDRVQcowState *s = bs->opaque;
70 90 int ret;
  91 +
  92 + if (cache_refcount_updates) {
  93 + write_refcount_block(s);
  94 + }
  95 +
71 96 ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
72 97 s->cluster_size);
73 98 if (ret != s->cluster_size)
... ... @@ -169,6 +194,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
169 194 int64_t offset, refcount_block_offset;
170 195 int ret, refcount_table_index;
171 196 uint64_t data64;
  197 + int cache = cache_refcount_updates;
172 198  
173 199 /* Find L1 index and grow refcount table if needed */
174 200 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)
181 207 /* Load or allocate the refcount block */
182 208 refcount_block_offset = s->refcount_table[refcount_table_index];
183 209 if (!refcount_block_offset) {
  210 + if (cache_refcount_updates) {
  211 + write_refcount_block(s);
  212 + cache_refcount_updates = 0;
  213 + }
184 214 /* create a new refcount block */
185 215 /* Note: we cannot update the refcount now to avoid recursion */
186 216 offset = alloc_clusters_noref(bs, s->cluster_size);
... ... @@ -199,6 +229,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
199 229 refcount_block_offset = offset;
200 230 s->refcount_block_cache_offset = offset;
201 231 update_refcount(bs, offset, s->cluster_size, 1);
  232 + cache_refcount_updates = cache;
202 233 } else {
203 234 if (refcount_block_offset != s->refcount_block_cache_offset) {
204 235 if (load_refcount_block(bs, refcount_block_offset) < 0)
... ... @@ -215,6 +246,10 @@ static int write_refcount_block_entries(BDRVQcowState *s,
215 246 {
216 247 size_t size;
217 248  
  249 + if (cache_refcount_updates) {
  250 + return 0;
  251 + }
  252 +
218 253 first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
219 254 last_index = (last_index + REFCOUNTS_PER_SECTOR)
220 255 & ~(REFCOUNTS_PER_SECTOR - 1);
... ... @@ -471,6 +506,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
471 506 int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
472 507  
473 508 qcow2_l2_cache_reset(bs);
  509 + cache_refcount_updates = 1;
474 510  
475 511 l2_table = NULL;
476 512 l1_table = NULL;
... ... @@ -563,11 +599,15 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
563 599 if (l1_allocated)
564 600 qemu_free(l1_table);
565 601 qemu_free(l2_table);
  602 + cache_refcount_updates = 0;
  603 + write_refcount_block(s);
566 604 return 0;
567 605 fail:
568 606 if (l1_allocated)
569 607 qemu_free(l1_table);
570 608 qemu_free(l2_table);
  609 + cache_refcount_updates = 0;
  610 + write_refcount_block(s);
571 611 return -EIO;
572 612 }
573 613  
... ...