Skip to main content

Module copy_data

Module copy_data 

Source
Expand description

Low-level data-copy primitive used by the copy path.

This replaces std::fs::copy so the copy path can keep the destination fd open across the data copy and the subsequent metadata operations (closing the TOCTOU window between writing bytes and setting times/owner/mode).

The copy uses a three-tier fallback chain, fastest first:

  1. the in-kernel copy_file_range syscall, which is reflink- and server-side-copy capable (e.g. on Btrfs/XFS/NFSv4.2);
  2. when the kernel or filesystem cannot satisfy that, a sparse-aware userspace copy that walks the source with SEEK_DATA/SEEK_HOLE and preserves holes;
  3. when the filesystem does not even support SEEK_DATA/SEEK_HOLE (some FUSE/older/unusual filesystems return EINVAL/ENOTSUP for those lseek whences), a plain dense read/write copy loop, which always works on any regular file (this mirrors what std::fs::copy would have done and exists purely for robustness — it does not preserve holes).

§Snapshot-size semantics

Callers pass len, the size captured when the source was classified. Both the primary and fallback paths copy up to len and agree on the result:

  • a source that grew after classification is intentionally not over-copied — we copy at most len bytes and dst ends at len;
  • a source that shrank below len (e.g. a concurrent truncate — holding the fd does not prevent it) copies and returns only what the source provides and sizes dst to that actual end, not to len (no spurious trailing padding);
  • a legitimate sparse trailing hole (the source’s logical size still equals len) keeps dst sized to len. Whether the trailing region is left unallocated depends on the path: the sparse-aware fallback (tier 2) preserves the hole, and the primary copy_file_range (tier 1) does so only on reflink/sparse-capable filesystems (e.g. Btrfs/XFS) — on others (e.g. ext4) the size is still len but the region may be fully allocated.

§Durability

These are synchronous syscalls, so once they return the writes are in the kernel. This function deliberately does not fsync/flush — durability is out of scope here. mtime correctness is the caller’s responsibility (it sets times after this returns).

Functions§

copy_file_range_all
Copy up to len bytes from src to dst using the in-kernel copy_file_range (reflink/server-side capable), falling back to a sparse-aware userspace copy when the kernel/filesystem can’t. Both files are already open; offsets start at 0. Returns the number of bytes copied.