The /fs hierarchy

Directories in /fs correspond to (and can replace) entries in /etc/fstab (or vfstab, or whatever your operating system uses). This hierarchy is intended to have the same structure on all systems. It is still experimental; this specification is subject to incompatible changes in the future, if they turn out to be needed for certain systems. If you know of systems where this scheme as currently specified would be problematic, please let me know. This design is discussed on the prjware list.

Specification

A filesystem is configured in a directory in /fs, e.g., /fs/std-root/ contains the configuration of the root filesystem. A directory in /fs has the following entries:

(All of these might be symlinks to files somewhere else, but they typically will not be, except perhaps dev, rdev, and check. In particular, mount directories should not generally be symlinks to traditional mount points such as /usr; see below.)

Entries in /fs may be symlinks, and a filesystem may have more than one name. Names beginning with std- are reserved for global use: they need not be present on every system, but when they are present, they should have the properties assigned here. Currently defined standard names:

Notes

When configuring a filesystem, I have an idea of which files I'll store on it, but I might change my mind later. Thus, every filesystem contains what looks like a subset of /; a filesystem shouldn't contain, e.g., /usr files directly, expecting to be mounted on /usr. Instead, it should contain a usr directory containing any /usr files on that filesystem. Files are never accessed by their names in /fs; instead, we set up symlinks such as /usr -> fs/stuff/mount/usr, and files are accessed via those symlinks. (It's like Plan 9, but without as much help from the kernel.) /usr itself is no longer to be thought of as a filesystem - even if there is one filesystem that contains all of /usr and only /usr, we've made the distinction between the filesystem storing the files and the name "/usr". A filesystem can become full. A part of the namespace cannot - we can always make symlinks to files stored on other filesystems. "lost+found" directories don't clutter up the namespace where files are accessed. Storing a file on a particular filesystem does not mean that it must appear in any particular part of the namespace (except under "/fs", where they're easily ignored). Even filesystems like /proc can be configured this way, but since we can't control their contents to the same degree as normal filesystems, /proc would be a symlink to fs/proc/mount instead of fs/proc/mount/proc.

There is no need for a filesystem configuration to specify whether it can be mounted by non-root users; that can be handled in general privilege-management tools like sudo.

Stupid symlink tricks

We can use symlinks to simultaneously satisfy these desirable conditions:

Similarly for a "home" filesystem and root's home directory. Things that must be on the std-root filesystem are stored in /slash, which (just like /fs/*/mount) looks like a subset of /. When pkgs is not mounted, we see:

lrwxrwxrwx /package -> fs/pkgs/mount/package
lrwxrwxrwx /fs/pkgs/mount/package -> /slash/package
drwxr-xr-t /slash/package
lrwxrwxrwx /slash/package/admin/daemontools -> daemontools-0.76
drwxr-xr-x /slash/package/admin/daemontools-0.76
lrwxrwxrwx /package/admin/daemontools = /slash/package/admin/daemontools
drwxr-xr-x /package/admin/daemontools-0.76 = /slash/package/admin/daemontools-0.76

When pkgs is mounted, we see:

lrwxrwxrwx /package -> fs/pkgs/mount/package
drwxr-xr-t /fs/pkgs/mount/package
lrwxrwxrwx /fs/pkgs/mount/package/admin/daemontools -> /slash/package/admin/daemontools
lrwxrwxrwx /fs/pkgs/mount/package/admin/daemontools-0.76 -> /slash/package/admin/daemontools-0.76
lrwxrwxrwx /package/admin/daemontools = /fs/pkgs/mount/package/admin/daemontools
lrwxrwxrwx /package/admin/daemontools-0.76 = /fs/pkgs/mount/package/admin/daemontools-0.76

The trick here is that the "pkgs" filesystem's "mount" directory is not empty when the filesystem is unmounted; there is a symlink in place of where the real contents would be, pointing to the portion of the packages that are available on the std-root filesystem. We don't have to create another symlink for each package on the "pkgs" filesystem - just one for each on the std-root filesystem; there are fewer of these, so we can forget about this trick most of the time. Also, installing a package on the "pkgs" filesystem doesn't require any modifications to the std-root filesystem, so std-root can be read-only. This trick can be used for other contents of other filesystems as well, but it will apply to a directory (and its descendents), not necessarily a package. In /package, packages just happen to correspond to directories.

Using /fs

I use the scripts fscheck, fsmake, fsmount, and fsumount to work with my /fs filesystems. (I also use this fsck.reiser script as the /fs/*/check script for my ReiserFS filesystems.) Example uses are in my boot scripts. If you do not have minutils installed, you can substitute mount -n and umount -n for minmount and minumount. (I would use -n because /etc/mtab is a symlink to proc/mounts on my Linux systems. /etc/mtab is capable of being inaccurate if maintained by userspace code. /proc/mounts is always correct, though not quite as available.)

You may find this a useful addition to your shell startup script. (It may need to be in a script invoked in place of the shell, which then execs the interactive shell.) If your shell initializes $PWD to the symlink-free name of the current directory, and you'd rather not be bothered with which filesystem you happen to be on, then this will remove the "/fs/*/mount" prefix from $PWD.

case "$PWD" in
  /fs/*/mount/*) PWD="${PWD#/fs/*/mount}"; export PWD;;
  /slash/*)      PWD="${PWD#/slash}";      export PWD;;
esac

Related Links

Dan Rench has a similar scheme for user ids to replace /etc/passwd. See also tcb.