From: Ciro Iriarte <cyruspy@gmail.com>
To: pve-devel@lists.proxmox.com
Subject: Re: [RFC storage, qemu-server] offload full/live clone to storage backend
Date: Fri, 10 Jul 2026 07:18:08 -0700 (PDT) [thread overview]
Message-ID: <6a50ff20.d6ce4a42.63dff.76fa@mx.google.com> (raw)
In-Reply-To: <c231abb9-c340-432c-9728-5dc46f134c16@proxmox.com>
On July 9, 2026 9:56 am, Fiona Ebner wrote:
> Different storage types based on the same underlying technology (e.g.
> ZFS) could still do it. That said, I don't mind not designing for this
> but just for offloading between storages of the same type.
Thanks both for the thorough feedback. Consolidated reply and a revised
proposal below.
Accepted as-is:
- Base-class copy_image dies instead of returning undef (only reachable
when the plugin advertises the capability).
- Drop "atomically" -- the plugin owns cleanup and undoes its own
allocation on failure; I'll document that as the contract.
- Rename $vmid -> $target_vmid, and pass the target storage *config* so
the plugin can judge whether a source/target pair is a valid offload.
- copy-offload as a plain per-storage option that capable plugins honor.
- Baseline: offload only between two instances of the same plugin type,
the plugin deciding whether those instances can actually copy.
Cross-type stays out of scope; since offload is opaque to PVE there's
no volume_export/import-style lowering to generalize it, so I'll leave
room in the signature but not design for it.
The substantive point is separating two things "offload" blurs:
point-in-time consistency of the copy, and independence of the result.
Consistency: the bitmap + mirror model is the right completion path for
any *smeared* copy -- a non-atomic, out-of-band bulk copy written while
the source keeps changing. NFS 4.2 server-side copy (copy_file_range) is
exactly that. Migration (move-disk, live migrate) needs it too, since
the target must converge to current state and cut over -- reusing the
replicated-migration mechanism fits well, agreed.
But snapshot-based backends never smear: rbd snap+clone, lvm-thin/btrfs
snapshots, zfs clone all copy from a static point-in-time source. There
a host-side drive-mirror only re-writes blocks that are already correct
-- not incorrect, just host I/O for work the array already did with
none. Those should skip the host mirror: freeze once (PVE already does,
per BlockJob.pm:168), snapshot/clone, thaw. That yields a valid
point-in-time clone -- same as the mirror-at-cutover PVE produces today,
minus the host data movement.
Independence differs per backend, and this is what determines whether a
snapshot is a valid *full* clone:
- lvm-thin, btrfs: reference-counted, independent immediately; source
can be removed at once.
- rbd: depends on a protected parent snapshot until `rbd flatten`
finishes; flatten runs on the Ceph cluster rather than as a host-side
qemu-img copy, but the dependency is real until it completes.
- zfs: a clone depends on its origin snapshot; `zfs promote` only
re-parents that dependency (no help when the template must stay the
clone source), and the only true full-copy route is a bulk send/recv,
which is not instant. So "instant + independent + host-free" isn't
achievable for zfs full clones -- that one wants the bulk path.
So copy_image should advertise which case it is, and the core needs an
independence barrier: the hook returns only once the target is
independent, or the core records the pending dependency and refuses to
delete the source/template/parent snapshot until the backend signals
completion. Otherwise "snapshot and return" is a broken full clone for
rbd/zfs.
Concretely, two capability classes on top of the option:
- copy-offload => atomic: static point-in-time source, no host mirror
(freeze -> snapshot/clone -> thaw [-> background flatten]).
- copy-offload => bulk: no instant independent snapshot -- needs a full
data copy (NFS 4.2 SSC, non-atomic SAN copy, zfs send/recv); the
running-VM case then needs the bitmap + mirror completion.
qemu-server then branches: atomic clones skip the mirror; bulk clones
and all move-disk/migration take the bitmap-seed + mirror path, reusing
the existing BlockJob.pm completion code.
Two QEMU details I'd like to confirm for the bulk path: the dirty bitmap
must be created before the array copy starts, so out-of-band writes are
tracked; and the target can't be attached writable during the copy --
blockdev-add + mirror only after the array reports the copy done, the
mirror then healing the tracked blocks.
Does that split sound acceptable? If so I'll send the pve-storage RFC
PATCH first (hook + option + capability + APIVER/APIAGE bump), then the
qemu-server consumer.
Thanks,
Ciro
prev parent reply other threads:[~2026-07-10 14:18 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 19:20 [RFC storage, qemu-server] offload full/live clone to storage backend Ciro Iriarte
2026-07-07 13:48 ` Fabian Grünbichler
2026-07-08 8:17 ` Fiona Ebner
2026-07-08 8:43 ` Fabian Grünbichler
2026-07-09 7:56 ` Fiona Ebner
2026-07-10 14:18 ` Ciro Iriarte [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6a50ff20.d6ce4a42.63dff.76fa@mx.google.com \
--to=cyruspy@gmail.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.