9ns: Add #gtfs
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 5 Apr 2018 19:03:14 +0000 (15:03 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:37:03 +0000 (14:37 -0400)
commit99d1ef5082d3193de1ea8fb485d2f08a12b92076
tree0e081b3e431baaaf8bced296dc423744ffa9c506
parent2ab1355ca1003d3c1e3bff8b696ce3e412334a66
9ns: Add #gtfs

gtfs is a generic tree file system that uses a somewhat arbitrary 9p device
for its backend - specifically #mnt.  #gtfs is the frontend caching layer
for the backend.  It has a page cache, a tree_file tree with RCU-protected
lookups, 'negative' entries, etc - all the things you'd expect.  If the
backend supports symlinks, then it would do that too.  Currently, #mnt does
not.

With this in place, we can mount 9p servers and execute binaries over 9p
with mmap, which wasn't possible before.

The neat thing about it is that it required no changes to the mount driver.

Brief background: the #mnt device is given a channel to a 9p fileserver and
attaches itself in your namespace.  You do an 'ls', which gets converted
into a bunch of operations in the kernel, and the #mnt device converts
those ops to 9p RPCs.  End result: it looks like the remote filesystem is
in your namespace.

The #gtfs takes a channel to *another* device, in this case the #mnt from
above, and when the kernel wants to do a bunch of ops, #gtfs uses the
tree_file code and page cache as a cache.  When it is missing certain info,
it talks to #mnt and gets the info from the remote server.  It does the
same trick as #mnt: take a channel that speaks a version of the 9p
protocol, and convert between two interfaces.  The difference?  #mnt uses
the RPC interface for 9p.  #gtfs uses the in-kernel *functional* interface
for 9p - which is the function pointers in struct dev (e.g. open, close,
read, write, etc).

You can see the caching layer's effect by watching the RPCs to the
fileserver.  When you do an ls, you see a read of the directory (readdir)
followed by a bunch of stat calls, which is the essence of ls.  If you do a
subsequent ls, you just see the read again.  No need to do the stat, since
the frontend cache already has the info.  Why do you need the read again,
you ask?  Because the frontend is a partial cache, and it doesn't
necessarily know about every file in a directory/tree.  So it checks with
the backend (the 9p server).  But for the files it has, it has all of the
metadata.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/Kbuild
kern/drivers/dev/gtfs.c [new file with mode: 0644]
kern/kfs/mountroot
kern/src/ns/chan.c
kern/src/ns/sysfile.c