Require full device flushes on Apple filesystems

Merged
VA
1d ago
+232-31

Apple Full durability previously called fsync, which does not drain the device cache. All Apple file/data flushes now share one implementation: Full uses F_FULLFSYNC; only ENOTSUP permits F_BARRIERFSYNC and then fsync. A successful weaker fallback returns Unsupported for Full, so callers cannot acknowledge full durability.

The public shared helper is acyclic_native_runtime::sync_file(file, Durability, meter). Existing stream callers already use it; co-approvals can select Barrier explicitly. Metered calls charge every actual syscall attempt, including fallbacks.

Validation:

  • ivar: CARGO_TARGET_DIR=~/mac-target/co-stream-c cargo test --locked -p acyclic-native-runtime --lib apple::flush::tests -- --nocapture: 2 passed, 0.04 s; successful build 41.08 s after reclaiming this lane's failed release incremental cache.
  • The counting seam intercepts the production flush syscall boundary. Full pins F_FULLFSYNC exactly; a negative control substitutes a real fsync and fails that pin. ENOTSUP fallbacks, other errors, and per-attempt admission counts are pinned.
  • bb1: focused native-runtime measured_sync_wait tests: 2 passed, <0.01 s (18.65 s build).
  • bb1 Windows GNU cargo check --locked -p acyclic-native-runtime --lib --tests --target x86_64-pc-windows-gnu: passed, 20.53 s. Combined remote wall time 116.3 s.

Decisions:

  • Preserve the existing public helper and return type. Unsupported reports a completed weaker fallback without inventing a durability receipt type.
  • Centralize Apple dispatch for metered and unmetered file flushes and sync_data, eliminating the duplicate fcntl path.

Fixes the pre-existing P1 dependency identified by rev-961. No merge requested.


Summary by cubic

Updates Apple flush logic so Full durability requires a device-level sync (F_FULLFSYNC) instead of fsync, which doesn't drain the device cache. If the filesystem only supports a weaker fallback, the fallback runs but Full returns Unsupported so callers never acknowledge durability they didn't get.

  • All Apple flush paths (sync_file, sync_data, etc.) now share the same implementation.
  • Only ENOTSUP triggers the fallback to F_BARRIERFSYNC and then fsync.
  • Interrupted flush syscalls are retried; every actual syscall attempt — including retries and fallbacks — is individually metered and admitted.