The fuse-backend-rs crate is an rust library to implement Fuse daemons based on the Linux FUSE device (/dev/fuse) or the virtiofs draft specification.
Linux FUSE is an userspace filesystem framework, and the /dev/fuse device node is the interface for userspace filesystem daemons to communicate with the in-kernel fuse driver.
And the virito-fs specification extends the FUSE framework into the virtualization world, which uses the Virtio protocol to transfer FUSE requests and responses between the Fuse client and server. With virtio-fs, the Fuse client runs within the guest kernel and the Fuse server runs on the host userspace or hardware.
So the fuse-rs crate is a library to communicate with the Linux FUSE clients, which includes:
The library is a Cargo workspace. The fuse-backend-rs crate at the root is a
thin facade that re-exports the sub-crates under crates/, so every historical
fuse_backend_rs::{abi, api, buffer, common, transport, passthrough, overlayfs}
path and every historical cargo feature (fusedev, virtiofs, vhost-user-fs,
async-io, persist, fuse-t, fusedev-uring) keeps resolving unchanged.
| Crate | Contents |
|---|---|
fuse-backend-core | The transport-neutral layers: Fuse ABI, API/server, buffers and common utilities. |
fuse-backend-vfs | The Vfs union multiplexer and its pseudo-fs backing store, plus the persist snapshot stack. |
fuse-backend-fusedev | The /dev/fuse transport, plus FUSE-over-io_uring and the macFUSE/fuse-t transports. |
fuse-backend-virtiofs | The virtio-fs transport, carrying Fuse requests over virtio descriptor chains. |
fuse-backend-passthrough | The passthrough filesystem driver (Linux-only). |
fuse-backend-overlayfs | The overlay filesystem driver stacking read-only layers under a writable one (Linux-only). |
Most users should keep depending on the umbrella crate, which bundles each transport with the drivers it has always shipped with:
[dependencies]
fuse-backend-rs = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs", features = ["fusedev"] }
Downstream crates that only need one layer can depend on a sub-crate directly and skip the rest of the workspace. For example, a filesystem built on the core ABI/API and the passthrough driver:
[dependencies]
fuse-backend-core = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs" }
fuse-backend-passthrough = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs" }
The sub-crates are not published to crates.io yet, so depend on the git repository directly for now.
Besides the traditional synchronous IO path, an asynchronous IO path is provided
through the optional async-io cargo feature, e.g.:
[dependencies]
fuse-backend-rs = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs", features = ["fusedev", "async-io"] }
The async-io feature is not part of a released crate version yet, so depend
on the git repository directly. Please note that the feature is still
experimental:
PassthroughFs currently relay requests to their
synchronous counterparts, so the blocking syscalls run in the context of the
async runtime. A native io_uring based implementation is planned for the future.To serve requests asynchronously, mount the filesystem through Vfs and drive a
FuseDevTask (fusedev transport) inside an async runtime, refer to
tests/async_smoke.rs for a working example.
A sample fuse server based on the Linux Fuse device (/dev/fuse):
use fuse_backend_rs::api::{server::Server, Vfs, VfsOptions};
use fuse_backend_rs::transport::fusedev::{FuseSession, FuseChannel};
struct FuseServer {
server: Arc<Server<Arc<Vfs>>>,
ch: FuseChannel,
}
impl FuseServer {
fn svc_loop(&self) -> Result<()> {
// Given error EBADF, it means kernel has shut down this session.
let _ebadf = std::io::Error::from_raw_os_error(libc::EBADF);
loop {
if let Some((reader, writer)) = self
.ch
.get_request()
.map_err(|_| std::io::Error::from_raw_os_error(libc::EINVAL))?
{
if let Err(e) = self.server.handle_message(reader, writer, None, None) {
match e {
fuse_backend_rs::Error::EncodeMessage(_ebadf) => {
break;
}
_ => {
error!("Handling fuse message failed");
continue;
}
}
}
} else {
info!("fuse server exits");
break;
}
}
Ok(())
}
}
This project is licensed under
Overall
Maintained
Code review
crates.io
Latest release
Releases this year
1,252 followers · starred Sep 2025
87 followers · starred Aug 2023
1,178 followers · starred Aug 2025
87 followers · starred Oct 2023
The fuse-backend-rs crate is an rust library to implement Fuse daemons based on the Linux FUSE device (/dev/fuse) or the virtiofs draft specification.
Linux FUSE is an userspace filesystem framework, and the /dev/fuse device node is the interface for userspace filesystem daemons to communicate with the in-kernel fuse driver.
And the virito-fs specification extends the FUSE framework into the virtualization world, which uses the Virtio protocol to transfer FUSE requests and responses between the Fuse client and server. With virtio-fs, the Fuse client runs within the guest kernel and the Fuse server runs on the host userspace or hardware.
So the fuse-rs crate is a library to communicate with the Linux FUSE clients, which includes:
The library is a Cargo workspace. The fuse-backend-rs crate at the root is a
thin facade that re-exports the sub-crates under crates/, so every historical
fuse_backend_rs::{abi, api, buffer, common, transport, passthrough, overlayfs}
path and every historical cargo feature (fusedev, virtiofs, vhost-user-fs,
async-io, persist, fuse-t, fusedev-uring) keeps resolving unchanged.
| Crate | Contents |
|---|---|
fuse-backend-core | The transport-neutral layers: Fuse ABI, API/server, buffers and common utilities. |
fuse-backend-vfs | The Vfs union multiplexer and its pseudo-fs backing store, plus the persist snapshot stack. |
fuse-backend-fusedev | The /dev/fuse transport, plus FUSE-over-io_uring and the macFUSE/fuse-t transports. |
fuse-backend-virtiofs | The virtio-fs transport, carrying Fuse requests over virtio descriptor chains. |
fuse-backend-passthrough | The passthrough filesystem driver (Linux-only). |
fuse-backend-overlayfs | The overlay filesystem driver stacking read-only layers under a writable one (Linux-only). |
Most users should keep depending on the umbrella crate, which bundles each transport with the drivers it has always shipped with:
[dependencies]
fuse-backend-rs = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs", features = ["fusedev"] }
Downstream crates that only need one layer can depend on a sub-crate directly and skip the rest of the workspace. For example, a filesystem built on the core ABI/API and the passthrough driver:
[dependencies]
fuse-backend-core = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs" }
fuse-backend-passthrough = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs" }
The sub-crates are not published to crates.io yet, so depend on the git repository directly for now.
Besides the traditional synchronous IO path, an asynchronous IO path is provided
through the optional async-io cargo feature, e.g.:
[dependencies]
fuse-backend-rs = { git = "https://github.com/cloud-hypervisor/fuse-backend-rs", features = ["fusedev", "async-io"] }
The async-io feature is not part of a released crate version yet, so depend
on the git repository directly. Please note that the feature is still
experimental:
PassthroughFs currently relay requests to their
synchronous counterparts, so the blocking syscalls run in the context of the
async runtime. A native io_uring based implementation is planned for the future.To serve requests asynchronously, mount the filesystem through Vfs and drive a
FuseDevTask (fusedev transport) inside an async runtime, refer to
tests/async_smoke.rs for a working example.
A sample fuse server based on the Linux Fuse device (/dev/fuse):
use fuse_backend_rs::api::{server::Server, Vfs, VfsOptions};
use fuse_backend_rs::transport::fusedev::{FuseSession, FuseChannel};
struct FuseServer {
server: Arc<Server<Arc<Vfs>>>,
ch: FuseChannel,
}
impl FuseServer {
fn svc_loop(&self) -> Result<()> {
// Given error EBADF, it means kernel has shut down this session.
let _ebadf = std::io::Error::from_raw_os_error(libc::EBADF);
loop {
if let Some((reader, writer)) = self
.ch
.get_request()
.map_err(|_| std::io::Error::from_raw_os_error(libc::EINVAL))?
{
if let Err(e) = self.server.handle_message(reader, writer, None, None) {
match e {
fuse_backend_rs::Error::EncodeMessage(_ebadf) => {
break;
}
_ => {
error!("Handling fuse message failed");
continue;
}
}
}
} else {
info!("fuse server exits");
break;
}
}
Ok(())
}
}
This project is licensed under
Overall
Maintained
Code review
crates.io
Latest release
Releases this year
1,252 followers · starred Sep 2025
87 followers · starred Aug 2023
1,178 followers · starred Aug 2025
87 followers · starred Oct 2023