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

Reply via email to