MoobFS

Documentation · Reproduce the tests

From a clone to a mounted layer.

MoobFS is an experimental kernel module for LLM-agent memory stored as plain files. This guide builds the tools, boots the disposable Linux VM that runs every test (the frozen M1 image, the stacked layer over ext4, btrfs and XFS, and the POSIX-authorized QUERY) and explains what each marker proves and does not prove.

Never load moobfs.ko or moobfs_layer.ko on your host: the harness boots a QEMU guest, and that is the only supported way to run the modules. Nothing has been released. Read the project goal and the division of responsibilities →

1. Build and test the host tools

You need a C11 compiler, Make and Python 3 on Linux or macOS. Run from the repository root:

git clone https://github.com/studiomoob/llmoobfs.git
cd llmoobfs
make test
printf 'A shared memory.\n' > build/memory.txt
build/host/mkfs.moobfs build/demo.img \
  alpha.txt=build/memory.txt beta.txt=build/memory.txt
build/host/fsck.moobfs build/demo.img

make test runs the unit tests of the typed attribute encoding shared by the module and the tools, plus nine image tests with 15 malformed variants. The verifier emits JSON: look for different inode numbers referencing the same object and physical offset. The creator refuses to overwrite an existing image. fsck.moobfs validates; it does not repair.

Compiling on macOS or on any Linux host tests nothing about the kernel code. The Linux-only xattr tools (moobfs-attr, moobfs-check, moobfs-index) are built by make attr-tools and used inside the VM.

2. Run the native Linux suite

Start Docker, then run:

make vm-test

The harness builds a Debian image pinned by digest with kernel 6.12.111+deb13-amd64 and its headers, compiles both modules and the test binaries against them, and boots that exact kernel in QEMU (TCG, no KVM, no privileged container, no network in the guest). The guest mounts the M1 image, then runs the layer suite over sparse ext4, btrfs and XFS disks: mount contract, pass-through tests, typed attribute tools, index and QUERY against the oracle, two-user isolation with ACLs, three fsx seeds, and the acceptance block with git, WAL-mode SQLite, dm-log-writes power-loss replay and dm-flakey error injection.

The first run downloads the Debian base and kernel packages. Apple Silicon uses x86 CPU emulation and is noticeably slower. The QEMU phase is bounded by a 600-second timeout; the CI job allows 35 minutes. Measured wall-clock times are not recorded yet.

Environment setup, the suite's variables and how to add a test: docs/development.md. Every marker, with what it proves and does not prove: docs/testing.md.

3. Read the markers

A run is read from build/vm/console.log. Success markers are printed only after the checks they summarize; a failure prints exactly one MOOBFS_VM_FAIL: <step> and stops. A successful run ends with:

SHARED: inode=2/3 physical=12288 length=16384
MOUNTED_READ_TESTS_PASS
WRITABLE_MOUNT_REJECTED
MOOBFS_VM_PASS: shared extents, independent inodes, reads,
readonly, remount, 15 malformed images
LAYER_LOWER_PASS: ext4 reflink=no
LAYER_LOWER_PASS: btrfs reflink=yes
LAYER_LOWER_PASS: xfs reflink=yes
MOOBFS_ACCEPTANCE_PASS: git, sqlite wal, memory client,
dm-log-writes replay, dm-flakey
MOOBFS_LAYER_PASS: pass-through over ext4, btrfs and xfs; ...

Long markers are printed on a single line. Expected noise that is not a failure: “Invalid argument” for the 15 malformed M1 images and the remount,rw attempt, the three invalid layer mounts at the start of the suite, and unsigned-module taint messages.

MarkerProvesDoes not prove
MOOBFS_VM_PASSM1 regression: two inodes share one physical extent (FIEMAP), reads match the fixture, read-write mounts and 15 malformed images are refused, module unloads cleanly.Anything about writes or other kernels; KASAN (the Debian kernel has none).
LAYER_LOWER_PASS: <fs>Over that lower filesystem: mount contract, pass-through behaviour with the same inode numbers and bytes visible below, typed attribute validation, index and QUERY equal to moobfs-index for ten predicates and after rename, directory rename, unlink, removexattr and remount, noindex and index_budget, two-user isolation with chmod and POSIX ACLs, idmapped and user-namespace mounts refused, a 5-second race of chmod/rename/unlink against QUERY, three fsx seeds, nolinks.Full POSIX conformance (xfstests has not been run), performance, behaviour with the index budget exhausted on large trees, timing channels.
MOOBFS_ACCEPTANCE_PASSOver ext4: git (three commits, fsck --strict), SQLite WAL with a concurrent reader keeps 200 of 200 rows, the memory-client convention works, power-loss replay to each mark shows every synced memory whole, write errors reach the caller and the tree is clean afterwards.The same over btrfs or XFS; crash consistency without the client's sync; read-error paths.
MOOBFS_LAYER_PASSThe three LAYER_LOWER_PASS lines, acceptance, module unload and a clean dmesg scan.KASAN/lockdep when printed by the Debian harness.
Evidence in build/vm/What it tells you
console.logEvery marker, every failure, the dmesg tail on failure.
environment.txtKernel, compiler, QEMU and package versions; SHA-256 of what was booted.
kernel.configThe exact kernel configuration that ran.
image-report.jsonThe fsck.moobfs report of the M1 fixture.

Journal entries record each phase: 0014 (index and QUERY), 0015 (acceptance and the two layer bugs it found), 0020 (QUERY authorization). CI results are visible in the Actions runs.

4. KASAN, UBSAN and lockdep

The Debian kernel has no sanitizers. A second workflow builds upstream 6.12.112 with vm/kasan.config (KASAN, UBSAN bounds, PROVE_LOCKING and related debug options) under virtme-ng and runs the same vm/suite.sh; success is MOOBFS_KASAN_PASS with no BUG, WARNING, KASAN, UBSAN or lockdep line in dmesg. It runs weekly, on demand and on pull requests touching layer/ or vm/. This harness found the third kernel-side defect (an uninitialized lock on an early mount failure, journal 0016). Step-by-step local reproduction is in docs/development.md, section 6. It covers the layer suite, not the M1 module.

Know the boundary of the result

What is delegated to the lower filesystem (journaling, reflink, dedupe, ACL evaluation) is not a property of MoobFS. See the architecture overview and the comparison.