macOS passthrough: bind mounts on FSKit filesystems (exFAT on macOS 15) fail with ENOENT because /.vol lookups are unsupported

Author: cameronkCreated Sep 13, 2026Updated Sep 19, 2026
LabelsFilesystemsVolumesMacOS

Summary

On macOS 15 (Sequoia) exFAT volumes are mounted by FSKit (mount shows the fskit flag). FSKit filesystems do not answer volfs lookups: open("/.vol/<dev>/<ino>") returns ENOENT for every inode on the volume. The macOS passthrough backend reopens every non-root inode through /.vol/<dev>/<ino> (crates/filesystem/lib/backends/passthroughfs/unix/inode.rs, get_inode_fd -> open_vol_fd, plus open_inode_fd, stat_inode, do_link, do_readlink, and the symlink metadata helpers). The mount therefore appears in the guest but every getattr, readdir, open on it fails with ENOENT.

Reproduction

Host: macOS 15.1.1, Apple Silicon, msb 0.6.15 (same code on v0.6.18 and main). No external drive needed; a 64 MB exFAT disk image mounts through FSKit on macOS 15.

$ sw_vers -productVersion
15.1.1
$ msb --version
msb 0.6.15

# 1. Create and mount a small exFAT volume, put a file on it.
$ hdiutil create -size 64m -fs ExFAT -volname msbexfat /tmp/msb-exfat.dmg
$ hdiutil attach /tmp/msb-exfat.dmg
$ mount | grep msbexfat
/dev/disk5s1 on /Volumes/msbexfat (exfat, local, nodev, nosuid, noowners, noatime, fskit, mounted by ck)
$ mkdir /Volumes/msbexfat/share && echo hello > /Volumes/msbexfat/share/hello.txt

# 2. The volume has no volfs: the /.vol/<dev>/<ino> path of the directory does not resolve.
$ stat -f 'dev=%d ino=%i %N' /Volumes/msbexfat/share
dev=16777239 ino=8 /Volumes/msbexfat/share
$ ls -d /.vol/16777239/8
ls: /.vol/16777239/8: No such file or directory

# The same lookup on an APFS directory works.
$ stat -f 'dev=%d ino=%i %N' ~
dev=16777229 ino=43588 /Users/ck
$ ls -d /.vol/16777229/43588
/.vol/16777229/43588

# 3. Bind-mount the exFAT directory: the mount appears in the guest but nothing under it resolves.
$ msb run --no-tty --mount-dir /Volumes/msbexfat/share:/share:ro alpine -- sh -c 'mount | grep share; ls /share; cat /share/hello.txt'
share_f2faf809 on /share type virtiofs (ro,relatime)
ls: /share: No such file or directory
cat: can't open '/share/hello.txt': No such file or directory

# 4. Control: the same content on APFS.
$ mkdir ~/msb-apfs-share && echo hello > ~/msb-apfs-share/hello.txt
$ msb run --no-tty --mount-dir ~/msb-apfs-share:/share:ro alpine -- sh -c 'mount | grep share; ls /share; cat /share/hello.txt'
share_f2faf809 on /share type virtiofs (ro,relatime)
hello.txt
hello

# Cleanup
$ hdiutil detach /Volumes/msbexfat && rm /tmp/msb-exfat.dmg

The original report was an exFAT external drive; the disk image reproduces it identically.

Impact

Any host directory on a FSKit-backed filesystem is unusable as a bind mount on macOS 15+. Today that is exFAT external drives; Apple is moving more filesystems to FSKit, so the set will grow.

Proposed fix

Probe volfs once when the share is created (open /.vol/<root dev>/<root ino>). When the probe fails, run that share in anchor mode: keep the (parent inode, name) anchor per inode that the Linux backend already maintains (InodeData::anchor_parent, anchor_name, aliases), and reopen by an openat(O_NOFOLLOW) walk from the retained root fd with a (dev, ino) identity check after open, exactly as get_inode_fd_linux does. Shares where the probe succeeds keep the current /.vol path unchanged.

Trade-off: path-based reopen can go stale when a host-side process renames entries under the share; that is the same behaviour Linux already has. No protocol, CLI, SDK, database, or on-disk format changes.

One related finding from testing on the real volume: linux_errno_raw translates macOS EOPNOTSUPP (102) but not ENOTSUP (45), so an ENOTSUP from the host reaches the guest as EIO. FSKit exFAT answers ENOTSUP to linkat. That is a one-arm addition to the errno table; I would include it in the same PR as its own commit unless you prefer it separate.

I have a patch ready that is confined to passthroughfs/unix, shared/inode_table.rs, and that errno arm in shared/platform.rs, with a forced-fallback test suite that runs on APFS (so CI on macos-14 covers it) and an hdiutil exFAT fixture test: https://github.com/mobasi-ai/microsandbox/tree/macos-anchor-mode-volfs-fallback. Happy to open the PR if this direction works for you.

Source: superradcompany/microsandbox