ref: afd49c3300fd489dedb79e0085da2a3627b1f3ec
parent: 3b24ef12df70101f54d1feb5658fd974f7a518e6
author: kvik <kvik@a-b.xyz>
date: Sun Oct 4 10:53:26 EDT 2020
namespace-lifting: add drafty version
--- /dev/null
+++ b/namespace-lifting.md
@@ -1,0 +1,111 @@
+# Namespace lifting
+
+The usual model for using Plan 9 namespaces is to have a single leader
+process construct a namespace by mounting resources that are known to be
+needed by it or its kids. The kids assume that their dependencies are
+available at known locations and will often fail to run entirely if they
+can't find those, rather than trying to bring in the missing pieces
+themselves. A good example of this is the root namespace constructed by
+the boot process that mounts a network stack on /net. This then gets
+inherited by descendant namespaces and is expected to be available by
+all network programs.
+
+The graphical user environment follows a similar model. When a user
+logs in, a new namespace is forked from the root namespace and user's
+profile script is run by a shell running inside this namespace. A profile
+script's job is to mount and bind all the resources that a
+user might expect to need during a terminal session: a plumber, mail
+file server, factotum, and so on. After constructing the namespace rio
+is run in it as the last thing.
+
+Subsequently, new windows created by rio inherit a copy of its
+namespace. Forking this template namespace is the only namespace
+operation supported by rio. In particular, rio itself doesn't provide a
+way to modify its namespace.
+
+This can still be achieved by an unwieldy mechanism provided by a
+plumber's "Local" rule. The Local rule provides a command backdoor
+into the originating namespace and can be used to modify it.
+
+I propose an alternative technique based on pin(1), a pinned I/O shell.
+This idea is stole...*cough* inspired! by mycroftiv's hub(1) system
+management workflows.
+
+With pin we can "pin" a fully capable interactive shell running in the same
+namespace as rio, which can provide a more convenient way to
+interact with it. The way to do this follows. You'll have to grab and
+install a copy of mq(4) and pin(1), both available in the same git repo:
+
+ git/clone git://src.a-b.xyz/mq && cd mq && mk install
+
+Create a conveniently named pinned rc session right before starting rio,
+perhaps in your profile:
+
+ [plumber, upas/fs, etc.]
+ pin -n rio0
+ rio
+
+The -n flag prevents pin from automatically attaching to the session,
+otherwise the I/O on the pinned shell would bleed into rio's GUI.
+
+Now that the rio is running we can create a window and attach to the
+shell just created. For lack of a better name we'll call this shell a control
+shell:
+
+ pin rio0
+
+To show that we can modify rio's namespace from this shell let's bind
+something and observe what happens. In the same pin window run:
+
+ bind /sys/src /n/src
+
+Then, create a new window and check that the system's source code
+is indeed bound to a new name /n/src:
+
+ ls /n/src
+
+Careful readers will have guessed that this didn't change the namespaces
+of windows that were created prior to us changing rio's namespace.
+Remember that rio creates (almost) identical *copies* of its namespace
+for every new window, but these are in fact different entities independent
+of each other.
+
+This same trick can be applied in other contexts. An example that comes
+to mind is providing access to a namespace that is being exported over
+the network. Let's start by exporting an empty mountpoint, which we'll
+later populate using namespace ops from our namespace control shell.
+
+Firstly, we'll need to use srvfs(4) to create a persistent mountable
+namespace which we'll mount in the network listener and export with
+exportfs(4). You might have thought that we could use exportfs(4)
+directly but that way we'd be actually exporting a different namespace
+for each connection.
+
+Run
+
+ pin -n exportctl
+ srvfs export /n/export
+
+This will create a /srv/export pipe "containing" our namespace.
+Next we'll create a listener to export this pipe to network clients
+Exportfs with the -S flag can be used for the task:
+
+ aux/listen1 tcp!*!999 /bin/exportfs -S /srv/export
+
+Let's see if we can connect, run the following:
+
+ srv tcp!your.ip.or.name!999 export /n/export
+
+This should mount our directory to /n/export on the client side. Run
+`ls /n/export` and assert that it's empty.
+
+Now let's change the exported namespace using our `exportctl` pin
+on the server machine.
+
+ pin exportctl
+ bind /usr /n/export
+
+Go back to the client machine and run the `ls /n/export` again, this time
+user directories should show up.
+
+That's it folks. I'd like to hear if you find some other tricks to do with this.