Rust FUSE library for server, virtio-fs and vhost-user-fs
Design
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:
- ABI layer, which defines all data structures shared between linux Fuse framework and Fuse daemons.
- API layer, defines the interfaces for Fuse daemons to implement a userspace file system.
- Transport layer, which supports both the Linux Fuse device and virtio-fs protocol.
- VFS/pseudo_fs, an abstraction layer to support multiple file systems by a single virtio-fs device.
- A sample passthrough file system implementation, which passes through files from daemons to clients.
Examples
Filesystem Drivers
- Virtual File System for an example of union file system.
- Pseudo File System for an example of pseudo file system.
- Passthrough File System for an example of passthrough(stacked) file system.
- Registry Accelerated File System for an example of readonly file system for container images.
Fuse Servers
- Dragonfly Image Service fusedev Server for an example of implementing a fuse server based on the fuse-backend-rs crate.
- Dragonfly Image Service vhost-user-fs Server for an example of implementing vhost-user-fs server based on the fuse-backend-rs crate.
Fuse Server and Main Service Loop
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(())
}
}
License
This project is licensed under
- Apache License, Version 2.0
- BSD-3-Clause License