Sunday, April 7, 2013

How 9 speaks 9p

This is how the 9 kernel speaks 9p with the file server, in the common case of using a cache for program images so executables are cached.

Printing the current working directory

Let's start with pwd:

$pwd

The shell calls exec to run the command, and as a result, the kernel calls namec to translate the  name "pwd" into a Chan structure. A series of requests and replies for Walk are issued to locate pwd in the current directory and then in /bin. Because /bin is a union mount, it is responsible for further requests and replies until pwd is located.


Twalk tag 7 fid 275 newfid 273 nwname 1 0:pwd 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 170 newfid 273 nwname 1 0:pwd 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 166 newfid 273 nwname 1 0:pwd 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 90 newfid 273 nwname 1 0:pwd 
Rwalk tag 7 nwqid 1 0:(00000000000001b3 35 ) 



Still within namec, the file is opened, because exec called with the Aopen flag.

Topen tag 7 fid 273 mode 3
Ropen tag 7 qid (00000000000001b3 35 ) iounit 8192 



Back in exec, the kernel reads the first few bytes to check out which kind of executable it is (binary? interpreted?) and read the executable file header. The file was already in the cache, so the Chan is discarded and the cache used.

Tread tag 7 fid 273 offset 0 count 32
Rread tag 7 count 32 '000001eb 00004ba3 0000095c ...'

Tclunk tag 7 fid 273
Rclunk tag 7


Now, after executing pwd, the program calls the C library function getwd, which opens "." and
calls fd2path to retrieve the path from the kernel's Chan for the process current working directory, and the descriptor is closed.

Twalk tag 7 fid 275 newfid 273 nwname 0 
Rwalk tag 7 nwqid 0 
Topen tag 7 fid 273 mode 0
Ropen tag 7 qid (0000000000002003 139 d) iounit 8192 
Tclunk tag 7 fid 273
Rclunk tag 7



This makes a total of 10 RPCs for printing the current working directory, and by design, each one must wait for the previous one to complete.

Changing the working directory

Let's execute now cd:

$ cd /sys/src


The shell's built-in command cd issues a chdir system call, which walks to the new directory (starting from the root directory in this case) and then clunks the previous Chan for "dot".


Twalk tag 7 fid 66 newfid 274 nwname 2 0:sys 1:src 
Rwalk tag 7 nwqid 2 0:(165b 21 d) 1:(0000000000002003 139 d) 
Tclunk tag 7 fid 275
Rclunk tag 7


This time it's 2 RPCs.

Listing a directory

Now we list the current working directory:
$ls

Like before, the shell calls exec (to execute ls this time), which leads to several RPCs:


Twalk tag 7 fid 274 newfid 273 nwname 1 0:ls 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 170 newfid 273 nwname 1 0:ls 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 166 newfid 273 nwname 1 0:ls 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 90 newfid 273 nwname 1 0:ls 
Rwalk tag 7 nwqid 1 0:(000000000000412e 65 ) 
Topen tag 7 fid 273 mode 3
Ropen tag 7 qid (000000000000412e 65 ) iounit 8192 
Tread tag 7 fid 273 offset 0 count 32
Rread tag 7 count 32 '000001eb 0000b29f 00001288 00002988...'
Tclunk tag 7 fid 273
Rclunk tag 7

Now it's the time for ls to list the directory. It stats the target to see which file it must list.
Twalk tag 7 fid 274 newfid 275 nwname 0 
Rwalk tag 7 nwqid 0 
Tstat tag 7 fid 275
Rstat
Tclunk tag 7 fid 275
Rclunk tag 7


It then opens the target directory,

Twalk tag 7 fid 274 newfid 275 nwname 0 
Rwalk tag 7 nwqid 0 
Topen tag 7 fid 275 mode 0
Ropen tag 7 qid (0000000000002003 139 d) iounit 8192 

reads it all to print the entries,
Tread tag 7 fid 275 offset 0 count 8192
Rread tag 7 count 3373 '3a000000 00000000 80290000...'
Tread tag 7 fid 275 offset 3373 count 8192
Rread tag 7 count 0 ''


and closes the descriptor when done.
Tclunk tag 7 fid 275
Rclunk tag 7

In total, it required 15 RPCs.

Creating a file


We now create a file without writing anything into it.
$ >/tmp/x

This makes the shell issue a create system call, which plays a dance (within namec) like shown:
Twalk tag 7 fid 66 newfid 273 nwname 1 0:tmp 
Rwalk tag 7 nwqid 1 0:(0000000000003f73 0 d) 
Twalk tag 7 fid 172 newfid 275 nwname 1 0:x 
Rerror tag 7 ename file does not exist
Twalk tag 7 fid 172 newfid 275 nwname 0 
Rwalk tag 7 nwqid 0 
Tcreate tag 7 fid 275 name x perm --rw-rw-rw- mode 1
Rcreate tag 7 qid (000000000000dd06 0 ) iounit 8192 
Tclunk tag 7 fid 273
Rclunk tag 7
Tclunk tag 7 fid 275
Rclunk tag 7

It required 6 RPCs.