fix(hf): fs2 flock(2) silently no-ops on NFS / 9P / overlay-fs — headline invariant of #185 broken
- Dominant language
- Rust
- Stars
- 0
- Forks
- 1
- Avg merge
- 11m
- Merged PRs (30d)
- 77
Description
## Problem
`voxora-hf` was switched to `fs2 = "0.4"` in PR #207 / fix to #185. `fs2` invokes `libc::flock(fd, LOCK_EX | LOCK_NB)` directly (verified in the upstream `fs2-0.4.3/src/unix.rs:51-54`). The Linux `flock(2)` man page states: *"flock() does not work with NFS. Use fcntl(2) for NFS file locking."* Same deadness on 9P and partial deadness on overlay-fs.
The F1 headline — *"two concurrent resolves make exactly one set of HTTP requests"* — therefore fails in any non-local-FS deployment:
- Two voxora CLI processes on an NFS-mounted cache root each take a local-only flock.
- Both proceed past `acquire_lock` (`try_lock_exclusive` returns `Ok`) and both walk the slow path.
- Bandwidth doubles (or worse). Quietly — Linux logs nothing on this degradation.
Other targets affected:
- 9P / virtio-fs: `ENOSYS` or silently no-op depending on the daemon.
- overlay-fs: depends on backing filesystem; CI's `runs-on: ubuntu-latest` is local so this never surfaces in PR CI.
## Recipe
Replace `fs2` with a Linux-OFD lock via `fcntl(F_OFD_SETLK)`. Wrap the libc calls in a thin safe module (the crate already has the precedent at `voxora-local/src/source.rs:268-275` for `O_NOFOLLOW`). The `unsafe` stays inside `voxora-hf` but the `#![forbid(unsafe_code)]` at `voxora-hf/src/lib.rs:1` still bites — promote the lock primitive to a new private module with `#![allow(unsafe_code)]` scoped to the lock file, OR use a maintained crate that exposes `fcntl(F_OFD_SETLK)` safely.
`fs2` removal also deletes the `LIBNAME` shim it pulled in (verified: `fs2` adds `libc` + `windows-sys` to `Cargo.lock`; the former was already present transitively).
Document the supported filesystems in `voxora-hf/src/cache.rs::acquire_lock` rustdoc ("local ext4 / xfs / tmpfs; not NFS / 9P / overlay-fs"). On unsupported mounts the implementation should fall back to a path-based `tokio::sync::Mutex` keyed by `cache::model_dir`, so the worst-case on NFS is "advisory serialisation through user-space" rather than silent corruption.
## Acceptance
- A new integration test mounts a 9P filesystem (the kernel source tree's tests/ subdir is a convenient 9P source for Linux runners; CI can be skipped on this leg) and asserts that two concurrent `HuggingFaceSource::resolve` calls make exactly one set of HTTP requests.
- The current `voxora-hf/tests/wiremock_concurrency.rs::parallel_resolves_complete_without_corruption` test still passes on ext4 with `expect(1)` budgets.
- The `fs2` dependency is removed from `voxora-hf/Cargo.toml`; `Cargo.lock` no longer carries the `fs2` package entry.
## Cross-references
Found during the F2 sweep after PR #207 landed. Member of EPIC #206.
Contributor guide
Research direction
Start with voxora-hf/src/cache.rs::acquire_lock, voxora-hf/src/lib.rs, and the O_NOFOLLOW precedent in voxora-local/src/source.rs:268-275. Read and run voxora-hf/tests/wiremock_concurrency.rs::parallel_resolves_complete_without_corruption before investigating the 9P integration-test setup. Done means concurrent resolves serialize on supported and unsupported filesystems, fs2 is removed, and the existing ext4 test and acceptance checks pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, rust
- Domain
- cli, operating-systems, testing
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 30/100