Kernel Mount (seaweed-vfs)

seaweed-vfs is a Linux kernel filesystem client for SeaweedFS — a real mount -t seaweedvfs mount, not FUSE. A thin kernel module handles the filesystem while a userspace daemon (sw-kd) does the SeaweedFS networking.

Why use it over FUSE?

  • Faster cached access — reads and metadata are served by the kernel, not handed off to a userspace process on every call.
  • Won’t run out of memory at scale — the mount process stays small whether it exposes thousands of files or tens of millions, so it can’t OOM the way a FUSE client’s growing inode map can.
  • Drop-in — a real mount you manage with mount, /etc/fstab, and systemd; restart or upgrade the daemon without unmounting.

Performance

What makes it faster than a FUSE mount:

  • Cached reads and metadata never leave the kernel. FUSE bounces essentially every VFS call out to a userspace process; the kernel mount calls the daemon only on a cache miss or a write — repeat reads, stats, and directory listings come straight from the kernel’s page and dentry caches.
  • Kernel readahead and the page cache accelerate sequential and repeated reads, exactly like a local filesystem.
  • An optional io_uring fast path (ublk-style) keeps many requests in flight for high-concurrency workloads; the default read()/write() channel is the fallback.
  • Memory scales with available RAM, not file count. The kernel mount uses memory in proportion to what the OS can spare — reclaimable cache the kernel frees under pressure — instead of growing with the number of files in the cluster the way a FUSE client does.

Throughput and latency vary by workload and hardware — these are architectural properties, not a published benchmark. The page cache, the kernel↔daemon split, and the memory model are covered in depth in the Kernel Mount technical reference.

Requirements

  • Linux, kernel 6.1 or newer (x86_64 or arm64).
  • A reachable SeaweedFS filer gRPC address — the filer’s HTTP port + 10000 (default 18888), e.g. filer.example.com:18888.
  • One of apt, dnf, yum, or zypper.

Install

A single command installs the kernel module and the daemon, builds the module for your running kernel (via DKMS), and — when you pass a filer — starts the daemon ready to mount:

curl -fsSL https://raw.githubusercontent.com/seaweedfs/artifactory/main/seaweed-vfs/install.sh \
  | sudo FILER=filer.example.com:18888 bash

It auto-detects your package manager, architecture, and kernel. Re-run the same command any time to upgrade in place.

Mount

sudo mkdir -p /mnt/seaweed
sudo mount -t seaweedvfs filer.example.com:18888 /mnt/seaweed

Or mount automatically at boot via /etc/fstab:

none  /mnt/seaweed  seaweedvfs  filer=filer.example.com:18888,_netdev  0 0

Then read and write /mnt/seaweed like any local directory:

ls /mnt/seaweed
df -h /mnt/seaweed

Unmount with sudo umount /mnt/seaweed.

Export over NFS (knfsd)

Experimental. A seaweedvfs mount can be re-exported to other hosts with the standard Linux kernel NFS server (knfsd) — no separate SeaweedFS NFS gateway, just /etc/exports. Machines without the kernel module (or a mixed fleet) then reach the same SeaweedFS namespace over NFSv4.

What makes this safe. NFS addresses files by an opaque file handle that must keep resolving after a file moves — and must never resolve to a different object if the original is gone. seaweed-vfs guarantees both:

  • A handle survives the rename of the file it names and the rename of any ancestor directory — the daemon maintains a forwarding index (O(1) work per rename, independent of subtree size) so a moved object stays reachable by its original handle, even across a daemon restart.
  • A handle that can no longer be resolved returns ESTALE — it never reads, writes, or stats another object that later took the old path. Every read, write, and attribute change carries the expected object identity, which the filer verifies atomically.

Why “experimental”: file handles are fully identity-checked, and directory handles are generation-verified (a deleted-and-recreated directory goes stale rather than resolving to the replacement). A few directory child operations (readdir, and create/unlink of children) are not yet parent-generation guarded, so a directory delete+recreate that races the cache-invalidation window is the remaining gap.

Requirements

  • The exporting host needs the kernel NFS servernfs-kernel-server (Debian/Ubuntu) or nfs-utils (RHEL/SUSE), providing exportfs and rpc.nfsd — in addition to the seaweedvfs mount.
  • Export the mount as the NFSv4 root with fsid=0.
  • Multi-filer clusters need a shared filer store (an external metadata backend — SQL, Redis, Cassandra, etcd, … — that every filer points at). The rename-forwarding index lives in the filer KV; with per-filer embedded stores (leveldb/rocksdb) it is not shared, so a handle written via one filer would not resolve through another. A single-filer deployment (embedded store and all) needs nothing extra.

Example

Mount seaweedvfs, then export it:

sudo mount -t seaweedvfs filer.example.com:18888 /mnt/seaweed
# /etc/exports — fsid=0 makes the mount the NFSv4 export root
/mnt/seaweed  10.0.0.0/24(rw,fsid=0,no_subtree_check,sync)
sudo exportfs -ra

From a client:

sudo mount -t nfs4 server.example.com:/ /mnt/seaweed-nfs

Operations & reference

For pinned-kernel fleets with no compiler, Secure Boot signing, manual package install, building the module from source, and in-place upgrades, see Kernel Mount operations.