Notes on Plan9's 9P protocol
The 9P protocol is the protocol for network file systems used in Plan9. Plan9 is not a widely used operating system, but it’s widely considered more true to the Unix spirit than Unix is, coming from some of the same people who made Unix as well.
Overview
To get a rough idea of the 9P protocol, consider a system where all
the original core Unix syscalls (open
, close
, read
, write
,
…) are lifted to be remote procedure calls. These can be sent over
the network, making file systems in Plan9 network transparent.
9P’s RPCs are documented in Plan9’s man page section 5 (mirror). The supported methods are:
- Session control
version
to negotiate the protocol version.attach
andauth
for authenticating with the remote end and opening a session.flush
to cancel ongoing requests.
- Basic file operations:
open
clunk
(equivalent toclose
)read
write
- Working with directories
walk
to descend a directory hierarchy.stat
andwstat
for querying and modifying a directory entries (e.g. to rename files).remove
for removing file entries.
In addition, there is an error
response which may be returned as
response to any of these requests.
The handle to a file is called “file ID” (fid) in Plan9 lingo. This can be thought of as a file descriptor.
The 9P protocol does away with a bunch of complexities that Unix, and particularly Linux has started to have. Some of the non-supported features are:
- There is no
mmap
support in the protocol. This can’t be done over the network. Presumably it can be emulated within limits if needed. - No
ioctl
. Control-style operations are often done through reads and writes to special purpose files. There are often textual command languages. - There is a more blurry line between different file types as in Unix, where you can distinguish named pipes, device files and regular files.
Playing with Plan9port
An easy way to play with 9P is to install Plan9port, a Linux userspace port of Plan9’s core tools and wiring, which comes as installable package with many Linux distributions.
Plan9port includes the Plan9 compiler, the acme text editor and other
things, including source code. Many of these tools are exposing 9P
file systems over Unix sockets in the /tmp/ns.$USER.$DISPLAY
directory. You can get your exact location by running the namespace
tool:
$ namespace
/tmp/ns.me:0
$
For example, you might want to start up the factotum
authentication
service and have a peek at the created file system. Plan9port’s 9p
tool lets you do simple accesses from the command line:
$ /usr/lib/plan9/bin/factotum
$ ls $(namespace)
factotum
$ 9p ls factotum
confirm
conv
ctl
log
needkey
proto
rpc
$
There are also public 9P services, such as the Plan9 “sources”
repository. After the Bell Labs server went down, these continue to
be mirrored by services such as sources.9p.io
. The 9fs
script is
a wrapper for quickly mounting this remote service, but needs a little
modification for convenience:
$ cat $PLAN9/bin/9fs \
| sed -e 's/sources.cs.bell-labs.com/sources.9p.io/' > ~/9fs
$ chmod +x ~/9fs
$ ~/9fs sources
$ 9p ls -l sources
d-rwxrwxr-x M 0 9grid 9grid 0 Jul 15 2018 9grid
--rw-rw-r-- M 0 bootes sys 0 Jun 24 2013 _sources
d-rwxrwxr-x M 0 adm sys 0 Jul 15 2018 adm
d-rwxrwxr-x M 0 sys sys 0 Oct 28 19:18 contrib
d-rwxrwxr-x M 0 bootes sys 0 Jul 15 2018 dist
d-rwxrwxr-x M 0 sys sys 0 Jul 15 2018 extra
--rw-rw-r-- M 0 bootes adm 9142602 Jan 23 2015 lsr
d-rwxrwxr-x M 0 geoff nix 0 Jul 15 2018 nix
d-rwxrwxrwx M 0 glenda sys 0 Jul 15 2018 patch
d-rwxrwxr-x M 0 sys sys 0 Jul 15 2018 plan9
d-rwxrwxr-x M 0 sys sys 0 Jul 15 2018 wiki
d-rwxrwxr-x M 0 xen xen 0 Jul 15 2018 xen
$
Hint: To make browsing more convenient, you may also use the FUSE file system which comes with Plan9port:
$ 9pfuse unix\!/tmp/ns.$USER.:0/sources /tmp/sources $ ls /tmp/sources 9grid contrib extra nix plan9 wiki adm dist lsr patch _sources xen $
Looking under the hood
Let’s first read a small file from the Plan9 sources repo:
$ 9p read sources/plan9/NOTICE
Copyright © 2002 Lucent Technologies Inc.
All Rights Reserved
$
To look under the hood of 9P, we can use the 9p
tool’s -D
option
to print all requests and responses.
$ 9p -D read sources/plan9/NOTICE
<- Tversion tag 0 msize 8192 version '9P2000'
-> Rversion tag 65535 msize 8192 version '9P2000'
<- Tauth tag 0 afid 0 uname me aname <nil>
-> Rerror tag 0 ename authentication rejected
<- Tattach tag 0 fid 0 afid -1 uname me aname
-> Rattach tag 0 qid (0000000000000002 0 d)
<- Twalk tag 0 fid 0 newfid 1 nwname 2 0:plan9 1:NOTICE
-> Rwalk tag 0 nwqid 2 0:(0000000000081aa0 78 d) 1:(0000000000081d2d 1 )
<- Topen tag 0 fid 1 mode 0
-> Ropen tag 0 qid (0000000000081d2d 1 ) iounit 8168
<- Tread tag 0 fid 1 offset 0 count 4096
-> Rread tag 0 count 63 '436f7079 72696768 7420c2a9 20323030 32204c75 ...'
Copyright © 2002 Lucent Technologies Inc.
All Rights Reserved
<- Tread tag 0 fid 1 offset 63 count 4096
-> Rread tag 0 count 0 ''
<- Tclunk tag 0 fid 1
-> Rclunk tag 0
$
The 9p
tool opens the Unix socket at /tmp/ns.me.:0/sources
to talk
to the backend service.
The steps are:
- Version negotiation: Both sides confirm the 9P variant they want to speak.
- Authentication: The
auth
call is normally supposed to return an open file ID, over which to speak an authentication protocol. In this case, the service permits unauthenticated read accesses, so this is returning an error. - Attaching to the service, retrieving the desired root directory, in this case it’s just the root. (Note, the client picks which FID it would like to use for identifying files.)
- Walking down to the desired file from the root FID 0, yielding the new FID 1.
- Opening the FID for reading.
- Calling
read
until nothing is returned any more. - Closing the FID with
clunk
.