Skip to content
Tech HistoryDeep Dive Published Updated 7 min readViews unavailable

Plan 9 from Bell Labs: Per-Process Namespaces and 9P Resources

Trace Plan 9's per-process namespaces from Bell Labs research into mount, bind, union directories, and 9P, without conflating design with Unix containers.

Plan 9 from Bell Labs is often summarized as “everything is a file.” That phrase misses the system’s more distinctive engineering move: name many resources through file-like interfaces, connect services with a common protocol, and let a process assemble a private view of those resources. A machine’s files, devices, window system, remote services, and historical snapshots could participate in one namespace without requiring a single global naming tree.

The design belongs to a specific research history. Plan 9 began at Bell Labs in the late 1980s; the first edition appeared in 1992, and the 1995 system paper described the architecture while the project was still developing. The fourth edition, released in 2002, introduced 9P2000. Those dates matter: the original system paper, later editions, and the protocol revision are related but not interchangeable snapshots.

Three principles made the system cohere

The Bell Labs paper identifies three architectural principles: resources are named and accessed like files in a hierarchy; 9P provides a standard protocol for accessing those resources; and distinct hierarchies from different services can be joined into a private hierarchical namespace. The ideas reinforce one another. A common protocol makes a service mountable, while the namespace gives a user or process a consistent way to reach that service.

“Like files” is an interface choice, not a claim that every resource behaves like an ordinary disk file. A window system, a network stack, and a block of stored data have different operations and failure modes. Plan 9 presents many of them through file-oriented names and operations, but service-specific semantics remain. A client still needs to understand what a particular resource means and what the server supports.

The architecture also challenged the assumption that every user should customize one private workstation. In the research paper’s model, terminals, CPU servers, and file servers had different roles. A person could customize a session’s view of shared network resources rather than relying only on a machine-specific local arrangement. This was an architectural proposal and a working system, not a claim that every deployment used the same topology.

9P connected independently served trees

9P is a message protocol for operating on a file hierarchy supplied by a server. A client can communicate with a local or remote service using a connection prepared to exchange 9P messages. Plan 9’s mount operation attaches the server’s tree at a point in the current namespace. The server chooses the actual service behavior; the namespace supplies the client’s name for reaching it.

This division keeps two concerns separate. The protocol describes how a client asks for file-oriented operations; the namespace decides where a client sees the service. A service can therefore be available without every process having to use the same path, and multiple services can be combined into an environment meaningful to one user or task.

9P’s role changed over the system’s editions. The overview of Plan 9 records that work on a revision called 9P2000 began after the third edition’s 2000 release. The 2002 fourth edition introduced it, with changes including less restrictive name lengths, a last-modifier field in directory metadata, batched walk messages, and authentication files that moved authentication protocol details outside 9P itself. A historical article about the architecture should not project every 9P2000 detail onto the earliest system.

bind, mount, and union directories reshape names

The programmer’s manual documents three system calls for constructing namespaces: mount, bind, and unmount. mount attaches a server-provided tree. bind makes one existing file or directory appear at another name. unmount removes a selected binding or mounted tree. The command-line tools expose corresponding operations.

A simplified Plan 9 command example can prepend an application-specific directory to the existing /bin union:

bind -b /acme/bin /bin

The -b option puts the new directory at the beginning of the union, so a matching name there is found before a later member. bind -a appends a directory instead. With no union option, the target is replaced by the new file or directory. These are lookup-order rules, not a generic promise that the first file is copied over the second.

Creating files in a union adds another rule. The -c option marks a member as eligible for creation; a new file is placed in the first eligible union member, and creation fails if that directory is not writable. Therefore, union composition affects both lookup and write placement. Administrators and scripts should inspect the order and creation policy rather than assuming a single merged writable directory.

Mounting a remote tree is not just string substitution. The manual describes mount as using a file descriptor connected to a file server and notes that the server can expose a selected tree. Authenticated mounts involve separate authentication descriptors and tools. Namespace construction chooses the mount point; it does not erase the server’s authentication or authorization rules.

Private does not always mean one process only

Plan 9 documentation describes each process as having a mutable namespace, but the bind and mount system-call manual gives an important operational qualification: changes apply to the current process and other processes in its namespace group. Process creation choices determine whether a child shares that group or receives a new one. The practical model is a namespace that can be isolated and customized at deliberate process boundaries, not a rule that every system call instantly creates an independent namespace.

The manual’s namespace description files make this construction repeatable. A sequence of bind, mount, import, unmount, and directory-change operations can describe a namespace built from scratch. newns and addns are commonly used to construct it, often during initialization. That turns the environment from an undocumented collection of machine-wide mounts into explicit per-session or per-process configuration.

What the design did and did not promise

Plan 9 demonstrated that network services and local resources could share a naming model, and that users could build a tailored view without requiring one universal global namespace. The resulting ideas are useful to compare with later systems, but comparison is not proof of direct descent. A Linux mount namespace, a container root filesystem, a Plan 9 namespace, and a 9P mount have different mechanisms, authority models, and lifecycle boundaries. Sharing vocabulary such as “mount” or “namespace” does not make them equivalent security features.

Likewise, a custom namespace is not by itself a complete security boundary. It changes name resolution for processes in a namespace group; safety still depends on which services are mounted, the permissions of those services, authentication, process credentials, and how the namespace is shared. This is an operational conclusion from the documented mechanism, not a claim that namespace customization is useless for isolation. It is a reminder to state exactly which resource names a process can reach and which checks the server performs.

Why this was a durable systems idea

Plan 9’s historical contribution is not a single syscall or a slogan. It is the interaction of a network file protocol, file-oriented services, and mutable namespaces. The model gives an engineer separate levers: implement or expose a resource, connect it through 9P, place it at a useful name, and choose which processes share that view. It also makes limitations visible: names can be private while underlying servers remain shared, and a convenient hierarchy does not replace authentication or application semantics.

The design remains instructive because it asks a systems question that still matters: can users compose resources without hardwiring each service into every application? Plan 9’s answer was an explicit, process-oriented namespace over a common file protocol. Its history should be read as a concrete research architecture, not as a simplified ancestor of every modern container or filesystem mount feature.

Related:

Sources:

Comments