Skip to content

Filesystem in Userspace (aka FUSE)

Posted on:July 15, 2023 at 08:23 PM

FUSE allows clients to create their own filesystem in the user space without affecting or editing the kernel code in the Unix or Unix-like systems.

filesystem-in-userspace Photo by Cristina Gottardi Unsplash

With the help of the FUSE, no file system internals or kernel module programming knowledge are required. We can easily implement our own file system.

FUSE consists of three components:

Table of Contents

Open Table of Contents

How It Works

For implementing a new file system with FUSE, a handler application is required that links with the library libfuse

For example, if we create a file system at /tmp/fuse:

  1. A User executes ls -l /tmp/fuse for listing files in the directory.
  2. This command is redirected to the kernel’s VFS
  3. FUSE sends the command to the registered program handler by using libfuse as a bridge.
  4. The handler sends the response back to FUSE over libfuse then FUSE sends the response to the user using VFS.

fuse-work Image from Wikipedia

In the initiation, fuse.ko kernel module registers three file systems in the VFS:

  1. fuse: Stackable file systems like NFS, ecryptfs, etc.
  2. fuseblk: Created for the block file systems.
  3. fusectl: Assures monitoring of the state of the FUSE file system and managing it.

What is Stackable Filesystem?

In stackable file systems, data is not held by the file system itself instead another file system is used. (like delegation). It is like an abstraction that gets in the way of another filesystem. Stackable filesystems can be used for automatic encryption, compression, etc.

In the example below, the virtual file system ecryptfs is used for automatic data encryption when writing to disk. ecryptfs is using the ext4 file system under the hood.

stackable-fs Stackable Filesystem

The libfuse library provides functionality for mounting, unmounting the filesystem, reading messages from the kernel module, sending the response back to the kernel module, etc.

There are two different types of APIs in the libfuse:

  1. High-level synchronous
  2. Low-level asynchronous (Communicated directly to the kernel module)

The handler application runs as a daemon generally.

Example FUSE applications: sshfs, ecryptfs

Creating a file system with FUSE, we should implement the fuse_operation struct for creating a file system with FUSE. (See Also: Struct fuse_operations)

struct fuse_operations {
    int (*getattr) (const char *, struct stat *);
    int (*readlink) (const char *, char *, size_t);
    int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
    int (*mknod) (const char *, mode_t, dev_t);
    int (*mkdir) (const char *, mode_t);
    int (*unlink) (const char *);
    int (*rmdir) (const char *);
    int (*symlink) (const char *, const char *);
    int (*rename) (const char *, const char *);
    int (*link) (const char *, const char *);
    int (*chmod) (const char *, mode_t);
    int (*chown) (const char *, uid_t, gid_t);
    int (*truncate) (const char *, off_t);
    int (*utime) (const char *, struct utimbuf *);
    int (*open) (const char *, struct fuse_file_info *);
    int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
    int (*write) (const char *, const char *, size_t, off_t,struct fuse_file_info *);
    int (*statfs) (const char *, struct statfs *);
    int (*flush) (const char *, struct fuse_file_info *);
    int (*release) (const char *, struct fuse_file_info *);
    int (*fsync) (const char *, int, struct fuse_file_info *);
    int (*setxattr) (const char *, const char *, const char *, size_t, int);
    int (*getxattr) (const char *, const char *, char *, size_t);
    int (*listxattr) (const char *, char *, size_t);
    int (*removexattr) (const char *, const char *);
};

Implementation for all functions of the struct is not necessary but they are required for our file system to work correctly.

We can select the FUSE version with macro #define FUSE_VERSION 22

Kernel module fuse.ko communicates with the libfuse using the character device /dev/fuse:

Fuse Communication

What are alternatives to FUSE?

Thanks for reading …


References