Designing FUSE: From Kernel VFS to Userspace and JuiceFS Performance
This article explains the evolution of file system architecture from kernel‑level VFS to userspace via FUSE, reviews the historical role of NFS, details JuiceFS's implementation on top of FUSE, and presents benchmark results that demonstrate its high throughput and practical limitations.
Kernel File Systems and VFS
Traditional file systems run entirely in kernel space, where privileged code manages core resources such as CPU, memory, disks, and network interfaces. System calls like open, read, and write act as bridges between user programs and the kernel, passing through the Virtual File System (VFS) layer, which provides a uniform interface for many different underlying file system implementations.
VFS abstracts the details of each concrete file system, allowing Linux to support dozens of file system types while keeping the kernel code stable and well‑tested.
Network File System (NFS) – First Kernel Breakthrough
As single‑machine performance became insufficient for growing workloads, NFS introduced a virtual storage layer that mounts remote directories as local paths. Applications continue to use standard file‑system calls, while the NFS client translates these calls into RPC requests sent over the network to a server that performs the actual operations.
This client‑server model inspired the later design of FUSE, which moves the server side into user space.
FUSE – Bringing File Systems to Userspace
In 2001, Miklos Szeredi created FUSE (Filesystem in Userspace), splitting the implementation into a kernel module and a user‑space library ( libfuse). The kernel module registers a character device /dev/fuse and forwards VFS requests to user space; the user‑space daemon processes these requests and returns results via the same device.
The request flow consists of three stages:
Request reception : The kernel registers /dev/fuse and the daemon reads requests with read(). If the request queue is empty, the daemon blocks.
Request handling : The daemon parses the packet, invokes the appropriate user‑space handler (e.g., read, write, create), and produces a response.
Result return : The daemon writes the response back to /dev/fuse; the kernel delivers it to the blocked system call, waking the application.
This design decouples kernel and user code, dramatically lowering the barrier to creating new file systems.
JuiceFS – A High‑Performance Distributed File System Built on FUSE
JuiceFS, launched in 2017, targets cloud‑native environments by using object storage as the backend and FUSE as the front‑end interface. After mounting, standard POSIX commands (e.g., ls, cp, mkdir) operate on the remote storage as if it were local.
The open‑file workflow is:
Mounting creates a go‑fuse module that opens /dev/fuse and spawns threads to read kernel requests.
An application call (e.g., open) goes through the C library, reaches VFS, and is handed to the kernel FUSE module.
The kernel packages the request and places it in the mount’s queue, waking a go‑fuse thread.
The go‑fuse thread parses the request and invokes the corresponding JuiceFS implementation.
The result is written back to /dev/fuse, waking the blocked application.
Because each request requires a user‑kernel context switch, performance concerns arise. JuiceFS addresses this with multi‑threaded handling and a smooth‑upgrade mechanism that keeps the mount file descriptor stable, allowing version upgrades without unmounting.
Performance Evaluation
On a 1.5 TB memory, 176‑core Intel Xeon machine, a 512 GB sparse file was created and read sequentially with fio to eliminate disk bottlenecks. Results:
Single‑thread bandwidth reached 2.4 GiB/s.
Increasing the thread count scaled linearly; at 20 threads the throughput hit 25.1 GiB/s, sufficient for most real‑world AI workloads.
JuiceFS also provides a CSI driver for Kubernetes, enabling non‑privileged containers to access the FUSE daemon safely and ensuring data durability in short‑lived pod scenarios.
Conclusion
FUSE decouples kernel and user space, offering developers a flexible way to implement custom file systems without kernel modifications. In cloud and distributed storage contexts, this flexibility enables projects like JuiceFS to deliver high‑performance, POSIX‑compatible storage that scales with modern workloads. Ongoing optimization work aims to further reduce the overhead of user‑kernel transitions and improve reliability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
