Backup and commit re-query the source block status for every task and
size a task by the copy buffer, so a long run of zeroes turns into a
crowd of small write-zeroes requests. This series reuses what the
up-front scan already learned and lets one write-zeroes task cover a
whole run.

Backup of a 16G qcow2 image holding 1G of data, the rest never
allocated, sync=full to a raw target on ext4:

               tasks    time
    before     16384    1.6s
    after       1088    1.0s

Such an image is the normal case rather than a corner one: a guest with
discard enabled on a disk which is mostly free leaves exactly this
shape behind.

Eric, this is the v4 you asked about on 10-28; please take it instead
of v3.

v4, all from Vladimir's review of v3:
- v3 5/9 "don't reserve memory for zero tasks" is dropped. On its own
  it let a write-zeroes task bounce through a buffer that s->mem never
  charged. Its accounting change moves into 12/12 and applies only to a
  task asking for BDRV_REQ_NO_FALLBACK, the one sure to need no buffer.
  Its Reviewed-by tags go with it.
- 7/12: each prescan step moves past the dirty area it searched, so a
  full backup of a fragmented source no longer searches the same range
  again and again.
- 8/12, 9/12 and 10/12 are new, the follow-ups asked for on v3 7/9:
  block_copy_is_cluster_allocated() becomes block_copy_scan_status(),
  the two prescan helpers merge into block_copy_prescan(), and
  zero_bitmap_valid becomes scan_done, published together with clearing
  skip_unallocated.
- 11/12 is new: co_get_from_shres() and co_put_to_shres() skip the
  mutex for zero bytes, which 12/12 makes the common case.
- 12/12: the serial fallback loop is gone. A refused task shrinks to one
  cluster and the rest of its range is dirty again, so it comes back as
  buffer-sized tasks running in parallel instead of one request holding
  off guest writes to the whole range. A task asking for NO_FALLBACK is
  left out of s->mem and of speed=. Widening uses
  bdrv_dirty_bitmap_next_zero(), drops the MAX() with cluster_size, and
  is no longer bounded by x-perf max-chunk, whose documentation now says
  so. Andrey's Reviewed-by on v3 is dropped since the patch changed.
- rebased on master

v3:
https://lore.kernel.org/qemu-devel/[email protected]/

Signed-off-by: Denis V. Lunev <[email protected]>
CC: Vladimir Sementsov-Ogievskiy <[email protected]>
CC: John Snow <[email protected]>
CC: Andrey Drobyshev <[email protected]>
CC: Eric Blake <[email protected]>

Denis V. Lunev (12):
  block/commit: pass BDRV_WANT_PRECISE to block-status
  iotests/040: cover large and fragmented commit runs
  block/commit: batch block-status queries
  iotests/124: cover backup of zero clusters and holes
  block/block-copy: extract block_copy_set_task_method()
  block/block-copy: track known-zero source clusters
  block/backup: pre-fill zero_bitmap for full/bitmap
  block/block-copy: rename block_copy_is_cluster_allocated()
  block/block-copy: merge the two backup scan steps into
    block_copy_prescan()
  block/block-copy: replace zero_bitmap_valid with scan_done
  util/co-shared-resource: skip the mutex for an empty request
  block/block-copy: coalesce write-zeroes tasks

 block/backup.c                 |  86 ++++----
 block/block-copy.c             | 326 +++++++++++++++++++++++++------
 block/commit.c                 |  58 ++++--
 include/block/block-copy.h     |   6 +-
 qapi/block-core.json           |   4 +-
 tests/qemu-iotests/040         | 102 +++++++++-
 tests/qemu-iotests/040.out     |   4 +-
 tests/qemu-iotests/124         | 347 ++++++++++++++++++++++++++++++++-
 tests/qemu-iotests/124.out     |   4 +-
 util/qemu-co-shared-resource.c |   8 +
 10 files changed, 829 insertions(+), 116 deletions(-)


base-commit: 73294d096cc591e122fde9e63db4739de6d84f2b
-- 
2.53.0


Reply via email to