dm-qcow2 processes every request sequentially in a single kwork. Unfortunately this introduces latency and cpu-bound limits. This patchset adds a fast path: right after splitting, qios which need no metadata changes are processed outside the main kwork, in parallel with it and with each other. These are: - reads and writes of fully allocated clusters; - reads of unallocated clusters, which are zero-filled or forwarded to the lower delta; - partial discards, which only punch a hole in the image file. Everything else (allocations, COW, compressed clusters, discards changing metadata, backward merge) still goes to the main kwork.
Fast path qios are batched in per-cpu llists and processed by one work per submitting CPU, to avoid queue_work() cost on every I/O. The target also declares DM_TARGET_NOWAIT now, so io_uring submits I/O inline instead of punting every request to io-wq. Patch 1 fixes a race with md page insertion which already exists between qcow2_llseek_hole() and the main kwork, and which the fast path makes more likely. Patch 3 counts a fast path write or partial discard in md writers under the lock which checks its L2 entry, so a discard unmapping the cluster waits for it before the cluster is freed. Known limitation: fast path reads are not counted, and nothing pins their cluster between the L2 parse and the data submit. Main kwork may discard the cluster, free it and reuse it for another allocation in that window, and a fast path read then returns the data of another guest offset. A follow-up series fixes this: https://virtuozzo.atlassian.net/browse/VSTOR-154659 The fast path can be turned off at runtime with the fast_path module parameter. v2: - patch 2 waits for L2 writeback, so a fast path write is not acked before its L2 entry is on disk - batching goes before DM_TARGET_NOWAIT, and its worker no longer loops unbounded - measurements moved to the thread - subject prefix changed to dm-qcow2 v3: - rebased on the new hci-dev top, which includes "dm-qcow2: let discards of one L2 page wait for in-flight writes together" - "wait for L2 writeback in perform_rw_mapped()" is replaced with "count fast path writes in parse_metadata()": a write to an L2 index in flight goes to the main kwork at parse, and a counted fast path write or partial discard is waited for by a discard unmapping its cluster, instead of rechecking the L2 entry in perform_rw_mapped() - new patch: fast_path module parameter - md page lookup is repeated once only - the known limitation of fast path reads is described Details are in the patches. https://virtuozzo.atlassian.net/browse/VSTOR-95494 Andrey Zhadchenko (8): dm-qcow2: repeat md page lookup if it was inserted in parallel dm-qcow2: prepare process_one_qio() for fastpath dm-qcow2: count fast path writes in parse_metadata() dm-qcow2: add per-qio work infrastructure dm-qcow2: implement per-qio fast processing dm-qcow2: add fast_path module parameter dm-qcow2: process fast path qios in per-cpu batches on a workqueue dm-qcow2: declare DM_TARGET_NOWAIT drivers/md/dm-qcow2-map.c | 279 +++++++++++++++++++++++++++++------ drivers/md/dm-qcow2-target.c | 12 +- drivers/md/dm-qcow2.h | 16 +- 3 files changed, 257 insertions(+), 50 deletions(-) -- 2.43.5 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
