macOS passthrough: bind mounts on FSKit filesystems (exFAT on macOS 15) fail with ENOENT because /.vol lookups are unsupported
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.dmgThe 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