-
Notifications
You must be signed in to change notification settings - Fork 14
Description
I don't understand why we're getting ESTALE sometimes in CI; haven't seen it locally. My understanding of the situations where this can happen require mutation of the source, but that shouldn't be happening here.
Investigation Summary (2026-01-23)
Assisted-by: OpenCode (Opus 4.5)
Scope of Impact
- Affected repos: Only
bootc-dev/bcvk(checked bootc, infra, ocidir-rs, containers-image-proxy-rs) - Frequency: ~5% of recent failed runs (5 out of ~100 runs checked)
- Tests affected: Various libvirt/to-disk integration tests:
test_to_disk_for_image_quay_io_fedora_fedora_bootc_42test_libvirt_run_bind_storage_rotest_libvirt_comprehensive_workflowtest_libvirt_port_forward_connectivity
Error Pattern
All failures occur in paths like:
/run/virtiofs-mnt-hoststorage/overlay/<layer-hash>/diff/sysroot/ostree/repo/objects/<xx>/<hash>.file
These are ostree content-addressed objects with many hardlinks (up to 970+ links for .file-xattrs-link files).
Architecture
Guest VM
└── virtiofs mount at /run/virtiofs-mnt-hoststorage
└── virtiofsd (v1.13.0, running unprivileged in container)
└── Host container storage (~/.local/share/containers/storage/overlay/...)
└── ostree repo objects (read-only, hardlinked)
Root Cause Analysis
-
bcvk passes
--inode-file-handles=fallbackto virtiofsd (seeqemu.rs:932), which should enable file handles when possible. -
However, virtiofsd runs unprivileged (inside a podman container with
--cap-add=all, but in a user namespace whereCAP_DAC_READ_SEARCHdoesn't grant real host filesystem capabilities). -
Without
CAP_DAC_READ_SEARCH, file handles don't work. From virtiofsd README:"virtiofsd can't use file handles (
--inode-file-handlesrequiresCAP_DAC_READ_SEARCH)" -
Fallback to O_PATH FDs: virtiofsd falls back to using O_PATH file descriptors to track inodes. When the guest wants to open a file, virtiofsd reopens via
/proc/self/fd/N. -
O_PATH FDs are vulnerable to ESTALE: According to virtiofsd docs, using O_PATH FDs instead of file handles "may also be important in cases where virtiofsd should only have file descriptors open for files that are open in the guest, e.g. to get around bad interactions with NFS's silly renaming."
The Puzzle
The container image layers are read-only - no files should be deleted or modified during the test. Yet we're seeing ESTALE. Possible explanations:
-
Inode generation mismatch: The kernel FUSE code checks
inode->i_generation != handle->generationand returns ESTALE on mismatch. virtiofsd always setsgeneration: 0, so this shouldn't trigger unless something is evicting/recreating inodes. -
Hardlink edge case: ostree objects have extremely high hardlink counts. There might be some edge case with how virtiofsd or the kernel handles lookups on highly-hardlinked files.
-
Race in inode cache: Something in the kernel's inode cache management could be evicting and revalidating inodes during concurrent access, causing transient failures.
-
Host filesystem peculiarity: Something specific to GitHub Actions runner filesystem configuration.
Relevant Code Paths
- virtiofsd inode store: When
--inode-file-handles=prefer/fallbackbut capabilities unavailable, falls back to O_PATH FDs (src/passthrough/inode_store.rs:405-417) - virtiofsd file open: Reopens via
/proc/self/fd/N(src/passthrough/util.rs:41-53) - Kernel FUSE staleness check:
fuse_stale_inode()infs/fuse/fuse_i.h:1080-1085
Example Failing Runs
- https://github.com/bootc-dev/bcvk/actions/runs/21287584864 (2026-01-23)
- https://github.com/bootc-dev/bcvk/actions/runs/21234542108 (2026-01-22)
- https://github.com/bootc-dev/bcvk/actions/runs/21210929456 (2026-01-21)
- https://github.com/bootc-dev/bcvk/actions/runs/21073791027 (2026-01-16)
- https://github.com/bootc-dev/bcvk/actions/runs/21002159880 (2026-01-14)
Potential Mitigations to Explore
- Run virtiofsd privileged: Grant
CAP_DAC_READ_SEARCHto enable actual file handles - Add debug logging: Capture virtiofsd debug output during failures
- Retry on ESTALE: Application-level workaround (not ideal)
- File upstream bug: With virtiofsd or kernel FUSE maintainers