ref: 765630adb6f6d6053bf8851ab15d0b8f6b42645f
parent: c49b41d1ece306c2b3a9732a77b412570e486d1d
author: kvik <kvik@a-b.xyz>
date: Wed Oct 28 15:28:43 EDT 2020
namespace-lifting: improve writing
--- a/namespace-lifting.md
+++ b/namespace-lifting.md
@@ -1,80 +1,77 @@
# 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
+process construct a namespace out of resources 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.
+available at known locations and will often fail to run entirely in their
+absence, rather than trying to bring in the missing pieces themselves.
+An example of this is the root namespace constructed by
+the boot process that mounts the network stack on `/net` and gets
+inherited by descendant namespaces. All networking programs
+simply expect the network resource there.
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
+logs in a new namespace is forked of the root namespace and their
+profile script is run by a shell within this namespace. The 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.
+file server, factotum, and so on. Rio is run on top of this namespace
+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.
+Subsequently, windows created by rio inherit a copy of this template
+namespace through forking. Forking is the only namespace
+operation directly provided by rio.
+In particular, rio 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.
+This can still be achieved by an unwieldy mechanism provided by
+plumber's "Local" rule. The Local rule is a command backdoor
+into rio's 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.
+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)` 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:
+namespace as rio, providing a familiar way of interaction. The way to do
+this follows.
+Grab 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:
+Pin a conveniently named rc right before starting rio, perhaps in your profile:
[plumber, upas/fs, etc.]
- pin -n rio0
+ pin -c 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.
+With rio running we can create a window and attach to the pinned shell.
+For lack of a better name we'll call this a control shell:
-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 -a rio0
- pin rio0
+To show that we can modify rio's namespace let's bind something an
+observe what happens. Run in the control shell:
-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:
+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.
+of windows that were created prior to 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.
+This same trick can be applied in other situations. An example that comes
+to mind is providing access to a namespace being exported over
+the network.
+Let's start by exporting an empty mountpoint, which we'll later populate
+using namespace operations from our 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)
@@ -83,11 +80,11 @@
Run
- pin -n exportctl
+ pin -c 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
+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
@@ -102,10 +99,10 @@
Now let's change the exported namespace using our `exportctl` pin
on the server machine.
- pin exportctl
+ pin -a exportctl
bind /usr /n/export
-Go back to the client machine and run the `ls /n/export` again, this time
+Go back to the client machine and run `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.