Fundamentals 10 min read

Understanding FUSE: Architecture and Implementation Details

FUSE implements a user‑space file‑system framework where a kernel module creates the /dev/fuse device and forwards VFS requests into kernel queues, while a multi‑threaded daemon reads these requests, optionally uses splice for zero‑copy, processes them, and writes replies back, enabling simple file‑system development without kernel recompilation.

OPPO Kernel Craftsman
OPPO Kernel Craftsman
OPPO Kernel Craftsman
Understanding FUSE: Architecture and Implementation Details

FUSE (Filesystem in Userspace) is a user‑space file system framework. With the support of the FUSE kernel module, developers only need to implement file‑operation callbacks provided by FUSE to create a new file system, without recompiling the kernel.

The architecture consists of a kernel module that registers a FUSE driver in the Linux VFS and creates the /dev/fuse character device, and a user‑space daemon (the FUSE daemon) that communicates with the kernel through this device. When an application performs a system call on a mounted FUSE file system, the VFS routes the request to the FUSE driver, which builds a fuse_request structure and places it in a kernel request queue. The calling process blocks while the FUSE daemon reads the request from /dev/fuse , processes it (often by invoking the underlying real file system such as EXT4 or F2FS), and writes a reply back to /dev/fuse . The driver then marks the request as completed and wakes the blocked process.

1. FUSE mount process

The mount operation uses the standard mount system call to bind a chosen mount point to /dev/fuse . All subsequent file operations under that mount point are handled by the FUSE file system and passed to the daemon via /dev/fuse .

2. FUSE daemon threading

The daemon creates a service thread that registers low‑level operations with libfuse via fuse_session_new . It then enters fuse_session_loop_mt , a multi‑threaded loop that reads requests from the kernel. Compared with a single‑threaded loop, the multi‑threaded mode can process several requests concurrently, improving throughput.

3. Zero‑copy with splice

By default the daemon reads requests with read() and writes replies with write() , incurring a kernel‑to‑user copy for each operation. FUSE can use the Linux splice system call to transfer data directly between two kernel buffers, avoiding the extra copy when the daemon implements the write_buf() method.

4. Kernel request queues

The kernel maintains five queues for FUSE requests: Background, Pending, Processing, Interrupts, and Forgets. Each request resides in exactly one queue at any time.

Background : stores asynchronous requests (reads by default, writes when write‑back cache is enabled).

Pending : holds synchronous requests (e.g., metadata) and a limited number of asynchronous requests (max 12) moved from Background.

Processing : contains requests currently being handled by the daemon.

Interrupts : highest‑priority queue for cancelled requests.

Forgets : used to delete cached inodes from the dcache.

5. /dev/fuse read/write flow

The driver registers fuse_dev_operations for /dev/fuse . The functions fuse_dev_do_read and fuse_dev_do_write correspond to the daemon reading a request and writing a reply, respectively. When all queues are empty, the read process sleeps; it is awakened as soon as a request arrives. After the daemon processes a request, it writes the result back, which is stored in a struct fuse_copy_state and copied to the original request via its unique identifier.

6. Example: unlink operation

When an application calls unlink on a FUSE mount point, the kernel creates an unlink request and wakes the blocked daemon. The daemon reads the request, parses it with libfuse, executes the corresponding operation, and writes the outcome back to /dev/fuse . The VFS then resumes the blocked system call and returns the result to the application.

Conclusion

FUSE greatly simplifies file‑system development by moving most logic to user space, but the additional kernel‑user transitions introduce performance overhead. Techniques such as splice‑based zero‑copy, multi‑threaded request handling, and write‑back caching are employed to mitigate these costs. Further performance optimizations remain an active research topic.

Reference: B. K. R. Vangoor, V. Tarasov, E. Zadok, “To FUSE or Not to FUSE: Performance of User‑Space File Systems,” FAST ’17.

multithreadingFUSELinux kernelFilesystem architecturelibfusespliceUser-space file system
OPPO Kernel Craftsman
Written by

OPPO Kernel Craftsman

Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.