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
