I have a complicated relationship with 9P2000.L. On the one hand it's been a 
useful way to build file systems for Linux, and I've gotten some mileage out of 
that. On the other hand, I'm not crazy about having a different protocol to 9P 
(I've read through a lot of what's been said on 9fans about this, going back 
many years).

I've been trying an experiment over the last few weeks to see if I can pass the 
extra Linux file system features over 9P (9P2000) as an application of 9P 
rather than using a separate protocol. I want to be able to connect two Linux 
machines using 9P, but have the full Linux file system semantics available 
across the connection: symbolic links, moving files and directories around, 
nanosecond time stamps, open modes, record locking, the whole bit. I also want 
that to work properly with a Plan 9 machine between them.
Linux programs should see a Linux file system, Plan 9 programs should see a 
Plan 9 file system.

I think it's easiest to explain by walking through an end-to-end example.

First, I altered my Linux 9P (9P2000) file server to offer an encoding of the 
linuxiness (is that a word??) For example, here's a test directory on my Linux 
machine. 

lyssa@pibysix:~/t $ *ls -l*
total 28
-rw-r--r-- 1 lyssa lyssa    6 Feb  8 11:41 bar
lrwxrwxrwx 1 lyssa lyssa    6 Feb  7 22:17 bin -> ../bin
-rw-r--r-- 1 lyssa lyssa    6 Feb 10 15:06 foo
-rw-r--r-- 1 lyssa lyssa    1 Feb  9 15:31 foop
-rw-r--r-- 1 lyssa lyssa    1 Feb  9 18:33 foop2
drwxr-xr-x 2 lyssa lyssa 4096 Feb  7 00:54 foot
lrwxrwxrwx 1 lyssa lyssa    3 Feb  7 01:06 hello -> foo
lrwxrwxrwx 1 lyssa lyssa    5 Feb 11 02:08 hello6 -> hello
-rw-r--r-- 1 lyssa lyssa   38 Feb  8 00:58 hi
lrwxrwxrwx 1 lyssa lyssa    2 Feb  9 01:28 hi2 -> hi
lrwxrwxrwx 1 lyssa lyssa   13 Feb 11 03:20 somenewlinkname -> one/two/three
lyssa@pibysix:~/t $

If I mount it on Plan 9 with my 9P server, it looks like this:

term% *pwd*
/usr/glenda/mnt/home/lyssa/t
term% *ls -lp*
--rw-r--r-- M 1061 glenda glenda  6 Feb  8 11:41 bar
d-rwxr-xr-x M 1061 glenda glenda  0 Feb  6 23:51 bin
--rw-r--r-- M 1061 glenda glenda  6 Feb 10 15:06 foo
--rw-r--r-- M 1061 glenda glenda  1 Feb  9 15:31 foop
--rw-r--r-- M 1061 glenda glenda  1 Feb  9 18:33 foop2
d-rwxr-xr-x M 1061 glenda glenda  0 Feb  7 00:54 foot
--rw-r--r-- M 1061 glenda glenda  6 Feb 10 15:06 hello
--rw-r--r-- M 1061 glenda glenda  6 Feb 10 15:06 hello6
--rw-r--r-- M 1061 glenda glenda 38 Feb  8 00:58 hi
--rw-r--r-- M 1061 glenda glenda 38 Feb  8 00:58 hi2
----------- M 1061 '(0)'  glenda  0 Jan  1  1970 somenewlinkname
term%

These files all behave as you might expect from a vanilla 9P server.
(the symbolic links are followed - the bottom one is a broken link. A long and 
involved conversation could be had about this, but can we not do that right 
now?)

I've added an invisible virtual extension to the namespace my Linux 9P server 
offers:
For any given file "/a/b/c/foo", there is a control file, "/a/b/c/,ctl/foo" 
which gives access to all its linuxy gloriousness:

term% *cat ,ctl/foo*
dev 45831
inode 265868
mode 0100644
nlink 1
uid 1001
gid 1001
rdev 0
size 6
blksize 4096
blocks 8
atime 1739199962
mtime 1739199962
ctime 1739466812
atimensec 460383798
mtimensec 470383712
ctimensec 926076796
name foo
term%

You can also write commands into these files to change some of the properties - 
as you might expect.
Here are the control files in the (unlisted) virtual directory ",ctl":

term% *ls -lp ,ctl*
--rw-r--r-- M 1061 glenda glenda 0 Feb  8 11:41 bar
--rw-r--r-- M 1061 glenda glenda 0 Feb  6 23:51 bin
--rw-r--r-- M 1061 glenda glenda 0 Feb 10 15:06 foo
--rw-r--r-- M 1061 glenda glenda 0 Feb  9 15:31 foop
--rw-r--r-- M 1061 glenda glenda 0 Feb  9 18:33 foop2
--rw-r--r-- M 1061 glenda glenda 0 Feb  7 00:54 foot
--rw-r--r-- M 1061 glenda glenda 0 Feb 10 15:06 hello
--rw-r--r-- M 1061 glenda glenda 0 Feb 10 15:06 hello6
--rw-r--r-- M 1061 glenda glenda 0 Feb  8 00:58 hi
--rw-r--r-- M 1061 glenda glenda 0 Feb  8 00:58 hi2
--rw-r--r-- M 1061 '(0)'  glenda 0 Jan  1  1970 somenewlinkname
term%

",ctl" is a simple example of a means to pass parameters down a Twalk to later 
requests by using weird file names.
You can pass other parameters...

term% *ls -lp ,nofollow*
--rw-r--r-- M 1061 glenda glenda  6 Feb  8 11:41 bar
a-r--r--r-- M 1061 glenda glenda  6 Feb  7 22:17 bin
--rw-r--r-- M 1061 glenda glenda  6 Feb 10 15:06 foo
--rw-r--r-- M 1061 glenda glenda  1 Feb  9 15:31 foop
--rw-r--r-- M 1061 glenda glenda  1 Feb  9 18:33 foop2
d-rwxr-xr-x M 1061 glenda glenda  0 Feb  7 00:54 foot
a-r--r--r-- M 1061 glenda glenda  3 Feb  7 01:06 hello
a-r--r--r-- M 1061 glenda glenda  5 Feb 11 02:08 hello6
--rw-r--r-- M 1061 glenda glenda 38 Feb  8 00:58 hi
a-r--r--r-- M 1061 glenda glenda  2 Feb  9 01:28 hi2
a---------- M 1061 glenda glenda 13 Feb 11 03:20 somenewlinkname
term%

This provides a way to avoid following the symbolic links.
Symlinks show up as append-only, read-only files, which is a bit of a hack, I 
suppose, but perhaps okay for now.
When you don't follow symlinks, they present their link target.

term% *cat ,nofollow/bin; echo*
../bin
term%

And you can access the control file of a link:

term% *cat ,ctl,nofollow/bin*
dev 45831
inode 263367
mode 0120777
nlink 1
uid 1001
gid 1001
rdev 0
size 6
blksize 4096
blocks 0
atime 1738966670
mtime 1738966670
ctime 1738966670
atimensec 484184178
mtimensec 484184178
ctimensec 484184178
name bin
symlink ..%2Fbin
term%

You can make new symbolic links from plan 9.
(where's that Linux ls(1) program?)

term% *ls -l ../../../bin/ls*
--rwxr-xr-x M 1061 '(0)' glenda 108752 Feb 28  2019 ../../../bin/ls
term%

Let's link to it:

term% *echo symlink ../../../bin/ls another >,ctl/,*
term% *ls -lp*
--rwxr-xr-x M 1061 '(0)'  glenda 108752 Feb 28  2019 another
--rw-r--r-- M 1061 glenda glenda      6 Feb  8 11:41 bar
d-rwxr-xr-x M 1061 glenda glenda      0 Feb  6 23:51 bin
--rw-r--r-- M 1061 glenda glenda      6 Feb 10 15:06 foo
--rw-r--r-- M 1061 glenda glenda      1 Feb  9 15:31 foop
--rw-r--r-- M 1061 glenda glenda      1 Feb  9 18:33 foop2
d-rwxr-xr-x M 1061 glenda glenda      0 Feb  7 00:54 foot
--rw-r--r-- M 1061 glenda glenda      6 Feb 10 15:06 hello
--rw-r--r-- M 1061 glenda glenda      6 Feb 10 15:06 hello6
--rw-r--r-- M 1061 glenda glenda     38 Feb  8 00:58 hi
--rw-r--r-- M 1061 glenda glenda     38 Feb  8 00:58 hi2
----------- M 1061 '(0)'  glenda      0 Jan  1  1970 somenewlinkname
term%

",ctl/," is a name for the control file for the directory itself.
Commands written there can be used to make symlinks, move files, etc.
It has an alias in the parent directory's ,ctl directory.


So that's the general idea. Linux extras are hidden from Plan 9, but accessible.


Second, I built an client adapter for Linux that uses these extra mechanisms. 
It serves 9P2000.L, which it mounts locally using v9fs - the Linux 9P client, 
but speaks "9P-with-benefits" across the network as a client. I have it in mind 
to do a version for FUSE one day, instead of using v9fs.

Exportfs on my plan 9 machine is serving the namespace above that included a 
mount of my Linux 9P server, above.
I've mounted that on Linux in /mnt/mnt. So now Linux is looking at Plan 9, 
which is looking at Linux:

lyssa@pibysix:/mnt/mnt/usr/glenda/mnt/home/lyssa/t *$ ls -l*
total 24
lrwxrwxrwx 1 lyssa lyssa   15 Feb 13 18:00 another -> ../../../bin/ls
-rw-r--r-- 1 lyssa lyssa    6 Feb  8 11:41 bar
lrwxrwxrwx 1 lyssa lyssa    6 Feb  7 22:17 bin -> ../bin
-rw-r--r-- 1 lyssa lyssa    6 Feb 10 15:06 foo
-rw-r--r-- 1 lyssa lyssa    1 Feb  9 15:31 foop
-rw-r--r-- 1 lyssa lyssa    1 Feb  9 18:33 foop2
drwxr-xr-x 2 lyssa lyssa 4096 Feb  7 00:54 foot
lrwxrwxrwx 1 lyssa lyssa    3 Feb  7 01:06 hello -> foo
lrwxrwxrwx 1 lyssa lyssa    5 Feb 11 02:08 hello6 -> hello
-rw-r--r-- 1 lyssa lyssa   38 Feb  8 00:58 hi
lrwxrwxrwx 1 lyssa lyssa    2 Feb  9 01:28 hi2 -> hi
lrwxrwxrwx 1 lyssa lyssa   13 Feb 11 03:20 somenewlinkname -> one/two/three

All that linuxy goodness is passed through Plan 9 as shown above. Linux does 
not expect file systems to follow
symbolic links themselves, so the adapter uses ",nofollow". Here's the same 
directory with the links resolved by Linux:

lyssa@pibysix:/mnt/mnt/usr/glenda/mnt/home/lyssa/t $ *ls -lL*
total 24
-rwxr-xr-x 1 root  root  108752 Feb 28  2019 another
-rw-r--r-- 1 lyssa lyssa      6 Feb  8 11:41 bar
drwxr-xr-x 2 lyssa lyssa   4096 Feb  6 23:51 bin
-rw-r--r-- 1 lyssa lyssa      6 Feb 10 15:06 foo
-rw-r--r-- 1 lyssa lyssa      1 Feb  9 15:31 foop
-rw-r--r-- 1 lyssa lyssa      1 Feb  9 18:33 foop2
drwxr-xr-x 2 lyssa lyssa   4096 Feb  7 00:54 foot
-rw-r--r-- 1 lyssa lyssa      6 Feb 10 15:06 hello
-rw-r--r-- 1 lyssa lyssa      6 Feb 10 15:06 hello6
-rw-r--r-- 1 lyssa lyssa     38 Feb  8 00:58 hi
-rw-r--r-- 1 lyssa lyssa     38 Feb  8 00:58 hi2
?????????? ? ?     ?          ?            ? somenewlinkname
lyssa@pibysix:/mnt/mnt/usr/glenda/mnt/home/lyssa/t $

Lets make a link on Linux, by passing the request through plan 9 and back to 
Linux:

lyssa@pibysix:/mnt/mnt/usr/glenda/mnt/home/lyssa/t $ *ln -s ../../../bin/ls 
another2*

* The "ln" command makes a symlinkat(2) system call into the Linux kernel.
* The v9fs driver in the kernel fields the call and issues a Tsymlink 9P2000.L 
message to my mounted adapter through a pipe.
* My adapter receives that and translates it into a 9P Twalk to the control 
file for the containing directory, Topens the file and issues a 9P Twrite with 
the "symlink" command in it, which goes over the network to Plan 9
* exportfs running on Plan 9 receives the Twalk, Topen and Twrite, and makes 
open(2) and pwrite(2) calls to the Plan 9 kernel.
* devmnt in the Plan 9 kernel - I think... - issues the same Twalk, Topen and 
Twrite requests over the network to my Linux 9P server.
* My 9P server receives the Twrite command and issues a symlinkat(2) system 
call.
* The Linux server kernel makes the symbolic link.

(there were some clunks and closes as well).

lyssa@pibysix:/mnt/mnt/usr/glenda/mnt/home/lyssa/t $ *ls -l*
total 24
lrwxrwxrwx 1 lyssa lyssa   15 Feb 13 18:00 another -> ../../../bin/ls
lrwxrwxrwx 1 lyssa lyssa   15 Feb 13 18:03 another2 -> ../../../bin/ls
-rw-r--r-- 1 lyssa lyssa    6 Feb  8 11:41 bar
lrwxrwxrwx 1 lyssa lyssa    6 Feb  7 22:17 bin -> ../bin
-rw-r--r-- 1 lyssa lyssa    6 Feb 10 15:06 foo
-rw-r--r-- 1 lyssa lyssa    1 Feb  9 15:31 foop
-rw-r--r-- 1 lyssa lyssa    1 Feb  9 18:33 foop2
drwxr-xr-x 2 lyssa lyssa 4096 Feb  7 00:54 foot
lrwxrwxrwx 1 lyssa lyssa    3 Feb  7 01:06 hello -> foo
lrwxrwxrwx 1 lyssa lyssa    5 Feb 11 02:08 hello6 -> hello
-rw-r--r-- 1 lyssa lyssa   38 Feb  8 00:58 hi
lrwxrwxrwx 1 lyssa lyssa    2 Feb  9 01:28 hi2 -> hi
lrwxrwxrwx 1 lyssa lyssa   13 Feb 11 03:20 somenewlinkname -> one/two/three
lyssa@pibysix:/mnt/mnt/usr/glenda/mnt/home/lyssa/t $

So now Linux can mount file systems over 9P, and still see all the nanosecond 
timestamps and other stuff:

lyssa@pibysix:~/mnt/mnt/usr/glenda/mnt/home/lyssa/t $ *stat foo*
  File: foo
  Size: 6               Blocks: 8          IO Block: 4096   regular file
Device: 36h/54d Inode: 265870      Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1001/   lyssa)   Gid: ( 1001/   lyssa)
Access: 2025-02-10 15:06:02.460383798 +0000
Modify: 2025-02-10 15:06:02.470383712 +0000
Change: 2025-02-10 18:32:05.271025091 +0000
Birth: -
lyssa@pibysix:~

(I suppose nanosecond resolution timestamps must be important to some people...)
My adapter is operating in a heterogeneous file system in this example, where 
part of it has this extended behaviour, and part of it does not. There's no 
mode switch or barriers - it just looks for the virtual files, and if they're 
not there it does the standard thing. If I'd bound some other part of the Plan 
9 space over part of the the mounted Linux space before I exported it, the 
adapter would just fall back to vanilla behaviour when file accesses are in 
that subtree.
It's a work in progress.
Linux is not actually my platform of choice, and symbolic links are not exactly 
my spirit animal, but it's a familiar context for exploring the ideas.

I don't know what people think?
This is about my third iteration of this idea. I'm not sure I'm done with it 
yet.
I wondering whether it would be better to have a single control file per 
directory and some kind of sub-protocol going through it. It would possibly be 
a less chatty alternative. But somehow not very appealing.
I'm open to suggestions.
------------------------------------------
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/T0f2c2342a05a3d6e-M9edffaa3ab33367c91c650f8
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to