FUSE inside gVisor: 4 KiB writes, no mmap, EINTR; checkout 2x slower
Four FUSE defects in the gVisor runsc builds we ran, what we patched, and what was still slow.
We ran a JuiceFS FUSE mount inside gVisor sandboxes in September 2026. Four behaviors of the runsc builds we ran broke it, and git failed on some of them.
The short answer
- Four defects: writes capped at 4 KiB, ENOSYS for mmap on FUSE files, fsync that returned before the daemon replied, and EINTR on ordinary signals. We patched all four in our runsc fork.
- Writes: a 64 MiB write took 16,447 FUSE WRITE requests at 34.6 MB/s. With only the
FUSE_BIG_WRITESflag added, it took 575 requests at 160.2 MB/s. - Git checkout of 9,749 files on the FUSE mount was still about twice as slow under gVisor as on the host kernel.
Checkout of 9,749 files on staging
| Where the checkout wrote | Runs | Time |
|---|---|---|
| Local directory, host kernel | 1 | 0.78 s |
| Local directory, under gVisor | 1 | 7.00 s |
| JuiceFS FUSE mount, host kernel | 3 | 39.7 to 43.5 s |
| JuiceFS FUSE mount, under gVisor | 3 | 83.8 to 90.1 s |
When the answer changes
- Where the numbers come from: most ran on one staging node that also ran CI. Only the 8.0 s cold start with a host mount and the
git resetfailure come from production. We did not measure concurrent mounts, checkpoint and restore, or cache invalidation between clients. - Upstream status on October 11, 2026: mmap on FUSE files still returned ENOSYS on master, and
FUSE_BIG_WRITESfirst shipped in release-20260928.0. We have not tested upstream's ERESTARTSYS change from October 8 or its open FUSE_INTERRUPT pull request. - Our own status: on September 25, 2026 we moved agent sessions to Firecracker microVMs, so these patches no longer apply.
The full post has the EINTR failures in git, the fsync test, and six checks to run before you use FUSE under gVisor.