Thursday, August 06, 2009

lab 104 - ducts: bi-directional mount channels

NAME

lab 104 - ducts: bi-directional mount channels

NOTES

Hi there, I want to talk to you about ducts. Are your ducts old fashion, out of date?

In this lab, I'll walk through a little facility I built to allow me to have bi-directional mounts over a single file descriptor channel. The nature of the way I access my Blue Gene environment requires me to do an awful lot over a single communications channel. I wanted the ability to both access the target node's file system while simultaneously exporting mine, while only using a single file descriptor.

To facilitate this, I wrote a little 9P-knowledgeable multiplexor which directs T-msgs to an export thread and R-msgs to a mount thread while multiplexing the responses from those threads back onto the same file descriptor.

The initial implementation of the base mechanism was relatively simple until I had to start considering how to clean things up when I started unmounting directories on one side or both. The liberal use of sys->pipe throughout the code meant it was somewhat difficult to detect when things were finished. I ended up adding a signaling packet to the protocol to notify the remote Duct when I had closed my mount, and then implemented a channel based monitor infrastructure so I could track what was still running and appropriately shut down the various pieces as things unmounted (it is possible to unmount one side without unmounting the other).

The interface is fairly simple, if using the module interface you spawn an uplink, specifying an input file descriptor and an output file descriptor for the connection (which may be the same FD), the path you wish to export and the mount point for where you want to place the imported file hierarchy.

If you are running it from the command line, it uses stdin and stdout for the input and output FDs and you only need specify the export path and mount point.

EXAMPLES

host1% listen -A tcp!*!1127 duct /usr/ericvh /n/foo

host2% dial -A tcp!host1!1127 duct /usr/inferno /n/bar

FILES

  • 104/duct.m
  • 104/duct.b

2 comments:

rog peppe said...
This comment has been removed by the author.
rog peppe said...

hmm, i probably spent too long writing it. damn. anyway, the gist was it's a nice idea; i've experimented with similar things in the past.

there's usually an asymmetricality between mount and export - you export once but you can mount many times, and this ducts program only mounts once. that would be easy to fix under plan 9 - just post into /srv, but you can't do that in inferno (i adapted ducts to use file2chan before i remembered that mount muxing is done per-file-descriptor).

as an experiment, i did a little adaptation to make it use my attach/auth-files-in-the-namespace inferno kernel (resurrected after several years), which works nicely. one line change,

< spawn mountit(inpipe[0], in);
---
> if(sys->bind("#M" + string inpipe[0].fd, in, Sys->MREPL) == -1)
> raise "cannot bind";

used like this:

% dial -A tcp!127.0.0.1!1345 duct.mux /appl /n/duct
% mount /n/duct/data /n/foo

of course, my modifications are highly unlikely to make into a mainstream kernel, but interesting nonetheless, i thought.

two other comments: i'm sure you're aware that Styx->MAXRPC is by no means that maximum possible styx packet size (64K is quite common when importing /dev/draw). it might be reasonable to eavesdrop on the initial styx negotiation and choose a buffer size according to the results.

and, i think you probably want to use styxlisten, not listen, as listen starts the program afresh for each connection, which isn't really what you want i think. you'd have to not automatically run in the background for this though.