Haiku UserlandFS: Follow a Mount from the Kernel to User Space
Trace Haiku UserlandFS add-on loading, request ports, worker threads, FUSE adaptation, and unmount behavior without assuming it is a security sandbox.
Haiku’s UserlandFS lets a filesystem implementation run in a user-space server while a kernel add-on connects it to Haiku’s filesystem interface. The useful operational model is not “the kernel has no filesystem code.” The kernel side still registers the filesystem, creates volumes and vnodes, handles VFS-facing callbacks, and exchanges requests with the server. The user-space side loads the filesystem add-on and services work sent across that bridge.
That split changes how to diagnose a mount. A failed operation may originate in the mount arguments, the kernel adapter, add-on discovery, symbol loading, request transport, a filesystem callback, or teardown. Treating every failure as a generic FUSE problem hides the layer that actually owns it. This article follows the current Haiku source tree’s implementation and uses an HFS+ FUSE add-on as one explicitly scoped example; it does not claim that every Linux FUSE program can be copied to Haiku unchanged.
Separate the VFS adapter from the filesystem implementation
The UserlandFS kernel add-on registers hooks with Haiku’s filesystem layer. Its kernel interface parses the mount arguments to identify a filesystem name and its parameters, then obtains or initializes the corresponding UserlandFS instance. The request protocol carries typed requests in both directions between the kernel adapter and server, so the bridge is not a single read/write pipe.
The server is a separate process. In the inspected source revision, userlandfs_server looks up the requested filesystem under the userlandfs add-on directory, loads the add-on, and resolves its userlandfs_create_file_system entry point. It then constructs request-port objects and starts request threads before announcing that the filesystem is ready. If the name is wrong, the add-on is absent, the image cannot load, or the required entry point is missing, mounting can fail before the filesystem’s own Mount() implementation has done useful work.
This is a bridge, not an automatic privilege boundary. The source demonstrates a kernel adapter and a user-space server, but that fact alone does not prove the server runs with a restricted identity, that every request is memory-safe, or that a filesystem bug cannot damage mounted data. Review the process credentials, mount mode, filesystem implementation, and data source independently.
Follow the mount and add-on startup sequence
In Haiku’s userlandfs_server command source, the usage text says the kernel module typically starts the server when a volume is requested to be mounted. It also says manual server startup can help with debugging and that the optional port argument is for the kernel module, not for a manual invocation. The server’s --help output is the safest first check on a target installation because a source-tree implementation and an installed release may differ.
The startup path has several distinct checkpoints:
- The mount request reaches the kernel-side UserlandFS hook with a filesystem name and add-on-specific parameters.
- The kernel module locates or registers the filesystem instance and coordinates with its server.
- The server searches its UserlandFS add-on locations and loads the named image.
- The server resolves
userlandfs_create_file_systemand creates the implementation object. - Request ports and worker threads are initialized; only then does the server announce readiness.
- The kernel-side mount callback completes the volume setup and returns a root vnode to the VFS.
When step 5 succeeds but the mount still fails, inspect the selected filesystem’s own Mount() path and arguments rather than repeatedly reinstalling the server. When the server never appears, check that the add-on name matches the actual installed filename and that the correct Haiku build includes the kernel adapter and server components.
For an HFS+ example, the hfsfuse project’s Haiku instructions say its make install step installs the program as a UserlandFS add-on. The project documents hfsfuse as read-only; it cannot write to or alter the target filesystem, so this command illustrates mount integration, not a write-test candidate. Its documented invocation is:
/system/servers/userlandfs_server --help
mount -t userlandfs -o "hfsfuse <options> <device>" <mountpoint>
The mount line is specific to that project’s integration and argument parser. Replace the placeholders only with values documented by the selected add-on. Do not interpret it as a universal UserlandFS syntax, and do not assume a filesystem is read-only merely because its source device is read-only or its mount command contains an unfamiliar option. Test with disposable data first.
Understand request dispatch and concurrency limits
After mount, VFS-facing filesystem operations cross from the kernel-side adapter to the server through request ports. RequestThread creates a port and a worker thread; the worker constructs a UserlandRequestHandler, which dispatches mount/unmount, vnode, file, directory, and related callbacks to the filesystem implementation. The reverse path is distinct: userland kernel-emulation helpers send requests to the kernel-side KernelRequestHandler for services such as vnode management, file-cache activity, iterative I/O, and node listeners or notifications. Do not confuse those kernel services with the ordinary VFS callbacks sent to the filesystem. This distinction helps narrow a hang: namespace operations can fail before file contents are read, and an I/O stall is not necessarily a mount-time discovery problem.
The implementation details are important but must not be mistaken for API promises. In the source revision pinned below, UserlandFSServer.cpp defines kRequestThreadCount as 10. That is a fact about the inspected source snapshot, not a documented guarantee for every Haiku release or every filesystem add-on. The FUSE adapter’s MainLoop() also contains a TODO to respect the FUSE multithreaded flag. Therefore, do not infer callback thread-safety, ordering, throughput, or a stable worker count from generic FUSE expectations. Inspect and test the exact adapter and filesystem version you are deploying.
The same caution applies to volume limits. The FUSE adapter’s CreateVolume() implementation currently returns B_BUSY when that FUSEFileSystem object already has a volume. That is a source-level behavior of this adapter, not a rule that every UserlandFS filesystem supports only one mount. If a second mount fails, determine whether the limitation is in the specific adapter, the add-on instance, the kernel registration path, or the filesystem itself before changing the mount topology.
Treat the FUSE adapter as a compatibility layer
Haiku’s source tree contains a FUSE-oriented adapter under UserlandFS. It provides a route for selected FUSE-style filesystems to implement their callbacks through Haiku’s bridge. That is not evidence that any Linux FUSE executable, shared library, mount helper, or kernel protocol implementation is binary-compatible with Haiku. An add-on may need a Haiku build, the project’s compatibility headers, a correctly exported entry point, and behavior supported by Haiku’s adapter.
The hfsfuse instructions make this distinction concrete: they say that on Haiku the FUSE program cannot be invoked directly and describe installing it as a UserlandFS add-on before mounting it through userlandfs. Use that project’s supported build/install procedure; do not copy an executable from Linux and expect Haiku to infer its ABI or callback contract.
Diagnose one layer at a time
Start with read-only observations. Record the Haiku release/build, filesystem add-on name, exact mountpoint and parameters, device identity, and whether the volume appears in the current mount list. Run the installed userlandfs_server --help to confirm that the command exists and that its arguments match the installed build. For a known add-on, check its own installation notes and verify that the named image is in the add-on location searched by the server.
Use the failure point to guide investigation:
- If the server reports that it cannot find the filesystem, verify the add-on name, install location, and architecture before changing the mount parameters.
- If the image loads but
userlandfs_create_file_systemis unavailable, verify that this is a UserlandFS add-on rather than an ordinary executable with a similar name. - If the server starts but mount initialization fails, compare the exact argument string with the add-on’s parser and inspect its mount callback’s error path.
- If mounting succeeds but directory lookup or reads hang, separate kernel-side request routing from server worker progress and the filesystem’s callback behavior. Capture a reproducible operation and inspect the relevant server and system diagnostics instead of repeatedly remounting valuable media.
- If a second volume returns busy, check for an adapter-specific limit such as the current FUSE adapter’s one-volume check; do not generalize that result to all UserlandFS clients.
Avoid debugging by killing the server while a volume is mounted. A normal unmount invokes the filesystem’s teardown path. In the current kernel adapter, userlandfs_unmount() calls the volume’s unmount hook, releases the volume reference, unregisters the filesystem, and returns the hook status. The source explicitly notes that the VFS considers the volume unmounted regardless of the filesystem hook’s return value. Consequently, an unmount return code is not proof that the add-on flushed every byte or that its cleanup completed correctly; validate data integrity and the specific implementation’s sync/unmount behavior separately.
For the FUSE adapter, FUSEVolume::Unmount() releases the root vnode and signals the FUSE client loop to exit. In the pinned source, fuse_main_real() then calls fuse_destroy(), but that shim is a TODO/no-op, so the normal FUSE destroy callback is not dispatched on this path. A normal Haiku unmount still invokes the volume-unmount hook; abruptly killing the server can skip even that flow. Validate the exact implementation’s teardown behavior rather than assuming the standard FUSE callback sequence ran, especially before relying on a writable filesystem.
Test safely before relying on a mounted volume
Use a disposable VM or expendable image and a documented read-only mode where the add-on supports one. Before a write test, make a separate backup and verify restoration. Exercise mount, directory enumeration, metadata lookup, small and large reads, expected error cases, sync, unmount, and remount. Compare hashes or filesystem-native checks where appropriate. If the implementation provides no tested read-only mode, treat it as writable and use only data you can lose.
Record the exact Haiku build, server and add-on versions, source or package revision, mount parameters, device identifier, test cases, and observed results. Repeat after changing the Haiku release or the add-on because the bridge, compatibility layer, and user-space callbacks may evolve independently. A successful mount proves only that the initialization path completed; it does not validate concurrent requests, crash recovery, durable writes, or every filesystem operation.
UserlandFS is valuable because it connects user-space filesystem implementations to Haiku’s native filesystem layer. Operational confidence comes from respecting the boundary it actually provides: kernel adapter, request transport, server, add-on, and mounted data each have their own failure and security properties.
Related:
- Haiku File-System Modules: VNode, Node, and Cookie Lifetimes
- BFS: How Haiku’s File System Doubles as a Database
Sources:
- Haiku UserlandFS server command source, pinned source revision
- Haiku UserlandFS developer guide, pinned source revision
- Haiku UserlandFS server initialization and worker setup, pinned source revision
- Haiku UserlandFS request worker, pinned source revision
- Haiku UserlandFS server-side filesystem request dispatcher, pinned source revision
- Haiku UserlandFS kernel request dispatcher, pinned source revision
- Haiku UserlandFS mount and unmount hooks, pinned source revision
- Haiku UserlandFS FUSE adapter, pinned source revision
- Haiku UserlandFS FUSE main-loop and destroy shim, pinned source revision
- Haiku UserlandFS FUSE volume teardown, pinned source revision
- HFSFUSE Haiku integration instructions