Status as of 2026-06-10. Bundled deliverable for WIN-TIER2.1 (Linux-only stub inventory on the Windows transfer path), WIN-TIER2.2 (upstream Cygwin rsync parity), WIN-TIER2.3 (known-failures closure mapping), and WIN-TIER2.5 (Tier 2 disclosure). WIN-TIER2.4 (performance bench cells) is deferred until Windows CI execution capacity is available.
Cross-references: the Windows support matrix at
docs/user/windows-support-matrix.md, the WIN-S series priority matrix
at docs/design/win-s8-windows-stub-priority-matrix.md, the
splice/vmsplice Windows-equivalent evaluation at
docs/design/windows-splice-vmsplice-equivalents.md, and the
sendfile/TransmitFile audit at
docs/design/win-s2-sendfile-transmitfile-audit.md.
Each row names a fast_io entry point that has a Linux implementation
and a non-Linux stub, the production call site (if any) that reaches the
stub on Windows, and the stub's observable failure mode. Call sites were
located by grep for the entry point across crates/ excluding
crates/fast_io/ to identify external consumers.
| Entry point | Linux impl | Non-Linux stub | Stub failure mode | Production Windows call site |
|---|---|---|---|---|
splice::try_splice_to_file |
crates/fast_io/src/splice/syscalls.rs:40 |
crates/fast_io/src/splice/syscalls.rs:281 |
Err(ErrorKind::Unsupported) |
None. Re-exported via crates/fast_io/src/lib.rs:283, no external caller. |
splice::try_vmsplice_to_file |
crates/fast_io/src/splice/syscalls.rs:211 |
crates/fast_io/src/splice/syscalls.rs:272 |
Err(ErrorKind::Unsupported) |
None. Re-exported, no external caller. |
splice::recv_fd_to_file |
crates/fast_io/src/splice/syscalls.rs:331 |
crates/fast_io/src/splice/syscalls.rs:357 (#[cfg(not(unix))]) |
Err(ErrorKind::Unsupported) |
None. The Windows receive path uses Writer::Iocp in crates/transfer/src/disk_commit/writer.rs:151. |
splice::SplicePipe::{new,with_capacity,splice_to_file,vmsplice_to_file} |
crates/fast_io/src/splice/mod.rs:131 |
crates/fast_io/src/splice/mod.rs:336 |
Constructor and methods return Err(ErrorKind::Unsupported); capacity() returns 0. |
None. Constructor exit is the safety boundary. |
vmsplice_writer::VmspliceFileWriter |
crates/fast_io/src/vmsplice_writer.rs:82 |
Compiled out: Writer::Vmsplice variant is #[cfg(all(target_os = "linux", feature = "vmsplice"))] |
Variant does not exist on Windows. | crates/transfer/src/disk_commit/process.rs:452 only on Linux. On Windows the dispatch falls through to Writer::Iocp or Writer::Buffered. |
io_uring module surface (shared_ring, per_thread_ring, file_reader, file_writer, disk_batch, linkat, statx, renameat2, send_zc, registered_buffers, buffer_ring, session_pool, cancel, linked_chain) |
crates/fast_io/src/io_uring/ |
crates/fast_io/src/io_uring_stub/ |
is_io_uring_available() returns false; constructors return Err(ErrorKind::Unsupported); opcode helpers return Err(ErrorKind::Unsupported). |
None on Windows. Writer::IoUring variant is #[cfg(all(target_os = "linux", feature = "io_uring"))]. Windows dispatches Writer::Iocp instead (crates/transfer/src/disk_commit/writer.rs:147). |
sendfile::send_file_to_fd |
crates/fast_io/src/sendfile/mod.rs:161 (Linux), :177 (macOS) |
crates/fast_io/src/sendfile/mod.rs:194 (#[cfg(not(unix))]) |
Silent data-discard: send_file_to_writer(source, &mut io::sink(), length) returns Ok(length). WIN-S.8 P1. |
None. Function is re-exported at crates/fast_io/src/lib.rs:278 but no external consumer wires it. Windows replacement TransmitFile lives at crates/fast_io/src/iocp/transmit_file.rs and is also not yet wired into the sender. |
sendfile::send_file_to_fd_with_policy |
crates/fast_io/src/sendfile/mod.rs:206 |
crates/fast_io/src/sendfile/mod.rs:236 |
Same io::sink() discard as above. |
None. |
Mmap, Landlock, O_TMPFILE, and copy_file_range stubs are inventoried
in the WIN-S.8 priority matrix and are excluded here because they are not
Linux-only in the same sense - Windows has equivalents already wired
(platform_copy::CopyFileExW, ReFS FSCTL_DUPLICATE_EXTENTS_TO_FILE,
FILE_FLAG_DELETE_ON_CLOSE) or the Linux primitive itself is not the
right reference point.
The WIN-S series tracks the per-stub replacement workstream:
- WIN-S.1 (#3242) - stub inventory parent; this audit consolidates it for the Linux-only subset.
- WIN-S.2 (#3243) - sendfile ->
TransmitFile. Backend shipped atcrates/fast_io/src/iocp/transmit_file.rs; sender wire-up tracked separately (no production caller ofsend_file_to_fdyet). - WIN-S.3 (#3244) - splice equivalent. Decision: permanent stub. See
docs/design/windows-splice-vmsplice-equivalents.md. - WIN-S.4 (#3245) - vmsplice equivalent. Decision: permanent stub (variant gated out on Windows).
- WIN-S.5 (#3246) - mmap_reader.
memmap2upgrade tracked under WIN-S.8.2. - WIN-S.6 (#3247) -
O_TMPFILE.FILE_FLAG_DELETE_ON_CLOSEalready shipped atcrates/fast_io/src/win_tmpfile/. - WIN-S.7 (#3248) - Landlock alternatives on Windows.
- WIN-S.8 (#3249) - priority matrix
(
docs/design/win-s8-windows-stub-priority-matrix.md). - WIN-S.9..S.11 (#3250-#3252) - send_zc, registered buffers, follow-up audits.
Upstream rsync's Windows story is Cygwin-only. The Cygwin port relies on the Cygwin runtime to translate POSIX syscalls into Win32 calls, which shapes what oc-rsync should match. For each Linux-only primitive above, this table documents Cygwin's behavior and oc-rsync's match status.
| Primitive | Upstream Cygwin behavior | oc-rsync Windows behavior | Match status |
|---|---|---|---|
splice(2) |
Cygwin exposes splice as a glibc-like wrapper. The Cygwin implementation does not use kernel-side zero-copy because Windows has no equivalent; it falls back to read() + write() internally. Upstream rsync code that calls splice therefore runs as a buffered copy with zero observable wire effect. |
try_splice_to_file returns Err(ErrorKind::Unsupported). No production caller wires it on Windows. The receive path uses Writer::Iocp (IOCP-batched WriteFile) which is strictly faster than Cygwin's userspace read/write. |
Match (oc-rsync ahead). Upstream falls back to userspace copy; oc-rsync uses IOCP. |
vmsplice(2) |
Cygwin does not expose vmsplice. Code that calls it returns ENOSYS. Upstream rsync does not call vmsplice on the receive path; the vmsplice Cargo feature exists only in oc-rsync as a Linux-only optimization. |
VmspliceFileWriter is compiled out on Windows (#[cfg(all(target_os = "linux", feature = "vmsplice"))]). The Writer::Vmsplice enum variant does not exist on Windows. |
Match. Both upstream Cygwin and oc-rsync skip vmsplice on Windows. |
io_uring |
Cygwin does not implement io_uring (no equivalent kernel interface). Upstream rsync has no io_uring code path at all. | io_uring_stub::is_io_uring_available() returns false. Writer::IoUring variant is gated out on Windows. IOCP is the production backend. |
Match (oc-rsync ahead). Upstream has no async I/O acceleration on Windows; oc-rsync uses IOCP. |
sendfile(2) |
Cygwin exposes sendfile and delegates internally to TransmitFile. Upstream rsync's sender uses buffered read + write rather than sendfile, so this is moot on the sender. |
send_file_to_fd on Windows is a stub that discards data via io::sink() (WIN-S.8 P1 latent defect). The Windows-native TransmitFile wrapper exists at crates/fast_io/src/iocp/transmit_file.rs but is not wired into the sender. |
Match in practice (neither implementation reaches the stub today). Latent defect: if a future change wires send_file_to_fd, oc-rsync silently discards data while upstream Cygwin would succeed via TransmitFile. WIN-S.8.1 fixes by returning Err(ErrorKind::Unsupported). |
Pipe creation for splice chain (SplicePipe) |
Cygwin provides POSIX pipes through pipe(2). Upstream does not chain splice through pipes on Windows because the underlying splice wrapper degrades to read/write. |
SplicePipe::new returns Err(ErrorKind::Unsupported). |
Match. Neither side establishes the pipe pair on Windows. |
recv_fd_to_file (high-level wrapper) |
No upstream analog; this is an oc-rsync abstraction over splice + read/write fallback. Upstream's read loop is read(socket) -> write(file) regardless of platform. |
recv_fd_to_file returns Err(ErrorKind::Unsupported) on #[cfg(not(unix))]. The Windows receive path bypasses this entirely via Writer::Iocp. |
Match. Neither side uses a unified fd-to-fd primitive on Windows. |
- IOCP file writes. Upstream Cygwin rsync writes files through
buffered
write(2)(translated toWriteFile). oc-rsync writes throughIocpDiskBatch, which submits overlapped writes with a single completion port wait per batch. This is faster than the Cygwin path and has no upstream analog. - IOCP socket I/O. Daemon and SSH transports use
WSARecv/WSASendwith overlapped completion. Upstream Cygwin uses blockingrecv/send. CopyFileExWdata-path dispatch. Local copies route throughplatform_copy::DefaultPlatformCopy, which preferentially usesCopyFileExWwithCOPY_FILE_NO_BUFFERINGfor files > 4 MB. Upstream Cygwin uses the standard read/write loop.- ReFS reflink. When the destination volume is ReFS, oc-rsync issues
FSCTL_DUPLICATE_EXTENTS_TO_FILEfor zero-copy clones. Upstream Cygwin has no reflink support on Windows.
These are documented as deliberate Tier 2+ advantages, not parity gaps.
tools/ci/known_failures.conf was inspected for Windows-specific
entries. The configuration contains no Windows-specific known
failures. All current entries are either:
- Upstream bugs (
standalone:upstream-compressed-batch-self-roundtrip). - Protocol-version downgrades (
up:acls,up:xattrs,up:compress-zstd,up:compress-lz4,up:merge-filter).
None of these depend on Linux-only stubs. The classification framework the task asked for - (a) closable with effort, (b) permanent gap on Linux-only feature, (c) different root cause - applies to potential future entries rather than current ones. For the WIN-P series planning horizon, candidate failure types and their classifications are:
| Candidate failure category | Classification | Rationale |
|---|---|---|
ADS-bearing files via --xattrs on Windows |
(c) different root cause - CLI preflight blocks --xattrs at crates/cli/src/frontend/execution/drive/workflow/preflight.rs:176; backend exists at crates/metadata/src/xattr_windows.rs. Tracked: PR #5564. |
Not a stub issue; preflight gate. |
| Long-path (>260 char) corner cases | (c) different root cause - missing \\?\ prefix helper. Tracked: PR #5575 (to_extended_path). |
Not a stub issue; helper missing. |
| OneDrive placeholder hydration | (c) different root cause - reparse-point classifier not wired. Tracked: PR #5579. | Not a stub issue; classifier missing. |
| Case-insensitive NTFS collision detection | (c) different root cause - no collision-detection layer. | Not a stub issue; layer missing. |
| Symlink transfer on Windows without admin/Developer Mode | (b) permanent gap - Windows requires elevation for symlink creation. | Not a stub issue; OS-policy. |
| POSIX device nodes / FIFOs on NTFS | (b) permanent gap - NTFS does not support mknod. Matches upstream Cygwin behavior. |
Not a stub issue; FS limitation. |
Sender zero-copy (sendfile) on Windows |
(a) closable - TransmitFile backend exists at crates/fast_io/src/iocp/transmit_file.rs; wire-up tracked under WIN-S.2. WIN-S.8.1 first hardens the stub to Err(Unsupported). |
Wirable with effort. |
Receiver splice zero-copy on Windows |
(b) permanent gap - no Win32 primitive matches splice pipe-mediated semantics. See docs/design/windows-splice-vmsplice-equivalents.md. IOCP is already faster than the Cygwin fallback. |
Permanent stub. |
Receiver vmsplice on Windows |
(b) permanent gap - same as splice. | Permanent stub. |
Priority list for the WIN-P series (#3681+) to attack:
- High value, closable. Sender
TransmitFilewire-up (after WIN-S.8.1 stub fix lands) - closes the only latent data-discard risk. - Medium value, closable.
MmapReaderupgrade viamemmap2to eliminate the doubled memory cost on checksums for large files (WIN-S.8.2). - Medium value, closable.
FILE_FLAG_DELETE_ON_CLOSEanonymous temp file wiring to replace the named-tempfile crash-debris pattern (WIN-S.8.3). - Low value, design-only. Landlock alternative selection between restricted tokens and AppContainer (WIN-S.8.4).
- No action. splice/vmsplice/io_uring stubs are correct and permanent.
The decision to mark Windows as Tier 2 (not Tier 1) is deliberate and based on three structural constraints:
- No CI runners under contributor control execute the full nextest
workspace on Windows. Required CI cells for Windows test only the
core,engine, andclicrates per the macOS/Windows scoping note. - No physical hardware coverage. WIN-G series (#3042+) tracks the gap; real-hardware NTFS testing is currently inferred from CI VM results.
- Permanent Linux-only primitives.
splice,vmsplice, andio_uringhave no Win32 equivalents. IOCP is the structural replacement and is faster than the upstream Cygwin fallback, but the public-facing claim of "full parity" would be misleading.
| Requirement | Current status | Owner |
|---|---|---|
| Full nextest workspace executes on Windows CI cells | Only core, engine, cli (and on some matrices metadata, apple-fs) |
WCI series (#3694-3705) |
| Physical NTFS hardware coverage (vs CI VM) | Not in matrix | WIN-G series (#3042+) |
Sender TransmitFile wired (closes WIN-S.8.1 latent risk) |
Backend shipped, wire-up pending | WIN-S.2 follow-up |
| ARM64 Windows build | Not in CI matrix | tracked separately |
--xattrs preflight gate widened |
CLI rejects on Windows; backend exists | PR #5564 |
Long-path \\?\ helper |
Missing | PR #5575 |
| Reparse-point classifier | Missing | PR #5579 |
| Case-insensitive collision detection | Missing | tracked under WPC-11 |
| Active Directory DACL fidelity | Audited, follow-up open | WPC-10 |
| OneDrive placeholder hydration | Blocked on classifier | PR #5579 |
Each of the above is independently shippable. Tier 1 promotion is gated on the CI and hardware coverage rows first - the missing features are then individually mergeable as PRs.
- Splice and vmsplice stubs are permanent. See
docs/design/windows-splice-vmsplice-equivalents.md. The receive path uses IOCP, which is strictly faster than the splice/vmsplice path would be on Windows even if the primitives existed. - io_uring stub is permanent. IOCP is the production Windows
backend. The 73 KB stub mirrors the cross-platform API surface so
call sites compile uniformly; see
project_io_uring_stub_size.mdfor the size note. send_file_to_fdio::sink()discard is a latent defect (P1). WIN-S.8.1 hardens the stub to returnErr(ErrorKind::Unsupported)before any production wire-up.TransmitFilewill be the Windows backend when the sender zero-copy path is wired.- Cygwin compatibility is an explicit non-goal. Users on Cygwin
should run upstream Cygwin rsync. See
docs/user/windows-support-matrix.mdsection 7.
- Parent: #2869 (Windows real-world parity series).
- WIN-TIER2 bundle (this doc): WIN-TIER2.1 (#4014), WIN-TIER2.2 (#4015), WIN-TIER2.3 (#4016), WIN-TIER2.5 (#4018).
- WIN-TIER2.4 (Windows perf bench cells, #4017): deferred until Windows CI execution capacity is available.
- WIN-S series (#3242-#3252): per-stub replacement workstream.
- WIN-P series (#3681+): Windows-only platform features.
- WCI series (#3694-3705): Windows nightly CI cell coverage.
- WIN-G series (#3042+): real-hardware validation.