On Fri, Oct 30, 2026 at 02:06:12AM +0100, Denis V. Lunev wrote:
> From: Denis V. Lunev <[email protected]>
> 
> Task size was capped to block_copy_chunk_size() regardless of method,
> which sizes a task by the copy buffer. A write-zeroes task carries no
> buffer, so that cap only splits one long known-zero run into a crowd of
> small COPY_WRITE_ZEROES tasks, each with its own request against the
> target.
> 
> block_copy_task_create() already decides from zero_bitmap how far a task
> may run, so add block_copy_widen_zero_area() to that decision: a
> write-zeroes task runs to the next clean cluster of copy_bitmap, at most
> BDRV_REQUEST_MAX_BYTES aligned down to cluster_size, and the existing
> clamp cuts it back to where the zero run ends. The experimental x-perf
> max-chunk does not bound it, and its documentation now says so.
> Widening is safe: an overlapping caller waits on the task's BlockReq via
> reqlist_wait_one() rather than observing it mid-flight.
> 
> A request that large is only cheap where the target zeroes by metadata.
> BDRV_REQ_NO_FALLBACK in supported_zero_flags rules out the targets which
> cannot, qcow2 v2 and iscsi among them, but it is optimistic for the
> rest: file-posix advertises it at open and only learns from a failing
> fallocate. So a write-zeroes task asks for it while the target is
> believed to oblige, which costs nothing when it does. A refusal ends the
> widening and shrinks the task to one cluster, written with fallback
> allowed. The rest of the range is dirty again, and the next pass of
> block_copy_common() picks it up as buffer-sized tasks running in
> parallel. Part of the refused range may already be zeroed, since
> -ENOTSUP only says the fast path is unavailable, and writing zeroes over
> it again changes nothing.
> 
> Such a task is also the only one sure to need no buffer: without
> NO_FALLBACK, bdrv_co_do_pwrite_zeroes() writes the zeroes out through a
> bounce buffer. So it alone is left out of the memory pool and of the
> rate limit, where one widened request would otherwise hold the job back
> for as long as speed= takes to pass its whole length. The one-cluster
> write left after a refusal is not charged either, though it may bounce:
> that is at most one cluster per worker, once, as tasks created after the
> refusal are charged in full.
> 
> Signed-off-by: Denis V. Lunev <[email protected]>
> CC: Vladimir Sementsov-Ogievskiy <[email protected]>
> CC: John Snow <[email protected]>
> CC: Andrey Drobyshev <[email protected]>
> ---
>  block/block-copy.c   | 96 +++++++++++++++++++++++++++++++++++++++-----
>  qapi/block-core.json |  4 +-
>  2 files changed, 88 insertions(+), 12 deletions(-)

Reviewed-by: Eric Blake <[email protected]>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org


Reply via email to