linux-2.0-transname.patch enables diskless clients, X-terminals etc to
mount the *root filesystem* of the server. This make administration of
large pools *a lot* easier.

The patch can be found at
   ftp://ftp.lmh.ox.ac.uk/pub/linux-kernel-patch-archive/
The author can be contacted under
   schoebel@informatik.uni-stuttgart.de
or snailmail
   Thomas Schoebel-Theuer
   Institut fuer Informatik
   Breitwiesenstr. 20-22
   D-70565 Stuttgart

Wherefore is linux-2.0-transname.patch?

Currently different diskless clients have their root "/" on different
directories on the server, beause each client has _some_ different
configuration files. However, most files (typically about 99%) have the same
contents on the clients and on the server, but have to be duplicated
(and maintained separately) just because about 1% of the files differ.
This duplication causes very large efforts in practice, since at least
the /etc directory has to be duplicated for every client. Even in /etc
many files are identical, for example sendmail.cf, initrc scripts and
others. Maintaining a large pool means to ensure coherence amoung the
duplicates. Classical methods like symlinks are unconvenient
for this task because they have to be valid in the view of mounted
filesystems at the client, not at the server.

linux-2.0-transname.patch overcomes this problem by allowing filenames
to be context-dependend. For example, if you have a file "/etc/config"
that should differ on the hosts "myserver" and "myclient", you just
create two different files named "/etc/config#host=myserver#" and
"/etc/config#host=myclient#". On host "myserver", the file
"/etc/config#host=myserver#" will appear as if it were hardlinked to
file "/etc/config" (without the #...=...# suffix). On host "myclient",
the corresponding other file will appear as "/etc/config". So you
can access the right file contents under the same name, depending
on which host you are.

A similar concept can be found in older HP-UX version, but with
so-called "hidden directories" which don't allow contemporary viewing
all versions by default. In contrast, our concept shows all context-dependent
files in the dir listing and they can be edited under the
fully qualified name.

An example for the use of linux-2.0-transname.patch:

For example, you can make your "/etc/fstab" context-dependend. If you want
to do that, you should create an "/etc/fstab#ktype=default#" for the
server and an "/etc/fstab#ktype=diskless#" for all clients. This is because
your clients may not yet know their own hostname when they attempt to mount
the root filesystem. You can compile in the kerneltypes "default" and
"diskless" into different kernels for servers and clients. Of course,
if your clients boot via bootp and know their names when mounting the root,
you can use "/etc/fstab#host=myclient#" instead. But at least servers
booting from disk normally dont know their hostname at root mount time,
so you can mix methods and use "/etc/fstab#ktype=default#" for the server,
"/etc/fstab#ktype=diskless#" for the majority of the clients and
"/etc/fstab#host=myclient#" for some specific client, because translation
of #host=...# is given precedence over #ktype=...# by default.

This sort of name translation works with any underlying file system
and with any inode type (i.e. with directories, symlinks, devices etc),
because it is implemented in the VFS layer of the kernel. Currently,
four types of default translations are supported:

 * <name>#host=<hostname>#  depends on the hostname, see "uname -n"
 * <name>#ktype=<string>#   works with a hard compiled-in string
 * <name>#machine=<id>#     depends on architecture, see "uname -m"
 * <name>#system=<id>#      currently only supported by Linux, see "uname -s"

Others may be added in future.

The kernel patch was developped for and is used at our Linux pool at the
University of Stuttgart with good results. Maintainance of the pool is
at a minimum, and adding new clients is a child's play. No worry with
keeping up mail configurations, newly installed tools, changed /etc/services,
/etc/shells, /etc/resolv.conf and many, many others. In contrast to a
sophisticated symlink solution, adding a new file to the /etc directory
is seen immediately by all clients. I never had less trouble with
administration before.

The only drawback is that administration tools currently aren't aware of
context-dependend files, so you cannot switch between contexts inside
one tool session. However, you can simulate administration sessions
on the server as if they were running on some client. To do this,
you have to set an environment variable NAMETRANS which has to be the
*first* environment variable in the list. For example, you can execute
'env - NAMETRANS=#host=mango#:#ktype=diskless# "`env`" command ...'
where the command will see the same files as if it had been executed on host
"mango" with a "diskless" kernel. Note that the colon-separated list
must specify full contexts beginning and ending with #. The specified
contexts will be tried in the specified order instead of the default
translations. To switch off translations entirely, use an empty list, e.g.
'env - NAMETRANS= "`env`" command ...'.

Hopefully the creators of administration tools and maintainers of Linux 
distributions will support changing environments in future, so that
maintaining different views will be very easy.

Some hints:

Archivers like tar, dump, restore should be used with translation
switched off, in order to avoid doubled space in archive files and when
extracting from them. Also, make sure that nfsd, mountd (and similar ones
like samba daemons) run without translation, in order to avoid doubled
(or even wrong) translation at the server and at the client. You can
automatically force the creation of context-dependent filenames if there
exists a template filename like "/etc/mtab#host=CREATE#". As soon as a
process running on "mango" tries to create a file "/etc/mtab", the version
"/etc/mtab#host=mango#" is created instead (which appears as hardlinked
to "/etc/mtab"). Note that if you want to make "/etc/fstab"
context-dependend, you should execute "touch /etc/mtab#host=CREATE#" and
"touch /etc/mtab.tmp#host=CREATE#", because mount, umount and others
running on different hosts would otherwise try to create one shared
/etc/mtab which would result in a clash. Also one should execute
"touch /etc/nologin#host=CREATE#" to prevent global side effects from
shutdown resp. runlevel.

How to install linux-2.0-transname.patch?

First of all, keep a backup of your kernel on your disk. Second, keep a
floppy with a miniroot handy, so you can boot from the floppy, mount
your harddisk root filesystem and change the names of your configuration
files back to their old names in case of emergency.

Then, unpack a *pristine* linux-2.0.tar.gz in directory /usr/src
(but first make a backup of your old /usr/src/linux), then say
"patch < linux-2.0-transname.patch". Check if everything goes right.
then "cd linux" and say either "make config" or "make xconfig"
(make menuconfig is not yet supported). In the section "filesystems",
many new options will appear. Take a look at the help texts that are
associated with the new options, they tell you further hints not
mentioned in this README. Then build your kernel as usual, install it
with a *new* kernel-filename, add a *new* entry to /etc/lilo.conf and run
lilo. DONT CHANGE any configuration files for the first reboot!
Just reboot the new kernel and play a little bit around with
creating context-dependend filenames in your home directory.
Try all modes including setting NAMETRANS to different values.

Hopefully some Linux distributions will support context-dependent
configurations in future. Support for future tools is already included in
the patch: When name translation is compiled into the kernel, a new file
"/proc/nametrans" will appear, whose contents shows the default translations.

But for now, you are on your own.
Before changing your system configuration files, make a plan and
be very careful; expect that reboots will hang if some essential
configuration file is translated wrong. Keep a bootdisk handy!

As an example for the changes necessary on our LST-based Linux pool,
here is the output of the command
"find / /tmp -xdev -name "*#*#" -print | sort -u | xargs ls -ld":

-r--r--r--   1 root     root         1725 Dec 21  1995 /etc/X11R6/xdm/xdm-config#host=eiche#
-r--r--r--   3 root     root         9509 Feb 15 17:35 /etc/XF86Config#host=balsa#
-r--r--r--   1 root     root         9401 Feb 15 17:34 /etc/XF86Config#host=eiche#
-rw-r--r--   1 root     root         9820 Feb 21 17:00 /etc/XF86Config#host=fichte#
-rw-r--r--   1 root     root         9822 Feb 14 15:45 /etc/XF86Config#host=laerche#
-r--r--r--   3 root     root         9509 Feb 15 17:35 /etc/XF86Config#host=mahagoni#
-r--r--r--   3 root     root         9509 Feb 15 17:35 /etc/XF86Config#host=palisander#
-r--r--r--   2 root     root         9509 Feb 15 17:41 /etc/XF86Config#host=pcbs10#
-r--r--r--   2 root     root         9509 Feb 15 17:41 /etc/XF86Config#host=pcbs11#
-rw-r--r--   1 root     root          586 Jun 11 23:13 /etc/fstab#ktype=default#
-rw-r--r--   1 root     root          242 May 29 17:35 /etc/fstab#ktype=diskless#
-rw-------   1 root     root          338 Jun 14 16:37 /etc/lilo.conf#host=eiche#
-rw-------   1 root     root         5236 Dec 16  1995 /etc/lst.cnf#host=balsa#
-rw-------   1 root     root         5254 Dec 16  1995 /etc/lst.cnf#host=eiche#
-rw-------   1 root     root         5236 Dec 19  1995 /etc/lst.cnf#host=fichte#
-rw-------   1 root     root         5236 Jan 11 13:47 /etc/lst.cnf#host=laerche#
-rw-------   1 root     root         5236 Feb 14 16:57 /etc/lst.cnf#host=mahagoni#
-rw-------   1 root     root         5236 Jan  4  1996 /etc/lst.cnf#host=palisander#
-rw-------   1 root     root         5236 Feb 15 13:57 /etc/lst.cnf#host=pcbs10#
-rw-------   1 root     root         5236 Feb 14 17:06 /etc/lst.cnf#host=pcbs11#
-rw-r--r--   1 root     root            0 Dec 18  1995 /etc/mtab#host=CREATE#
-rw-r--r--   1 root     root          157 Jun 23 21:16 /etc/mtab#host=balsa#
-rw-r--r--   1 root     root          466 Jul  1 16:15 /etc/mtab#host=eiche#
-rw-r--r--   1 root     root          239 Jul  4 11:10 /etc/mtab#host=fichte#
-rw-r--r--   1 root     root          239 Jun 18 14:17 /etc/mtab#host=laerche#
-rw-r--r--   1 root     root          239 May 23 10:50 /etc/mtab#host=mahagoni#
-rw-r--r--   1 root     root          239 Jul  3 10:36 /etc/mtab#host=palisander#
-rw-r--r--   1 root     root           47 Feb 15 14:57 /etc/mtab#host=pcbs10#
-rw-r--r--   1 root     root           47 Feb 14 20:04 /etc/mtab#host=pcbs11#
-rw-r--r--   1 root     root            0 Dec 18  1995 /etc/mtab.tmp#host=CREATE#
-rw-r--r--   1 root     root            0 Dec 19  1995 /etc/nologin#host=CREATE#
----------   1 root     root          115 Feb 15 14:57 /etc/nologin#host=pcbs10#
----------   1 root     root          115 Feb 14 20:04 /etc/nologin#host=pcbs11#
-rw-r--r--   1 root     root         4818 Dec 16  1995 /etc/system.cnf#host=balsa#
lrwxrwxrwx   1 root     root           25 Dec 22  1995 /etc/system.cnf#host=eiche# -> system.cnf#ktype=default#
-rw-r--r--   1 root     root         4821 Dec 19  1995 /etc/system.cnf#host=fichte#
-rw-r--r--   1 root     root         4824 Jan 11 13:47 /etc/system.cnf#host=laerche#
-rw-r--r--   1 root     root         4827 Feb 14 16:57 /etc/system.cnf#host=mahagoni#
-rw-r--r--   1 root     root         4833 Jan  4  1996 /etc/system.cnf#host=palisander#
-rw-r--r--   1 root     root         4840 Feb 15 14:10 /etc/system.cnf#host=pcbs10#
-rw-r--r--   1 root     root         4846 Feb 14 18:23 /etc/system.cnf#host=pcbs11#
-rw-r--r--   1 root     root         4818 Dec 13  1995 /etc/system.cnf#ktype=default#
drwxrwxrwt  16 root     root         3072 Jul  4 14:29 /tmp#ktype=default#
lrwxrwxrwx   1 root     root           26 Jul  4 14:22 /tmp#ktype=diskless# -> /tmp#ktype=default#/client
-rw-rw-rw-   1 root     root            0 Feb 15 14:57 /tmp/client#host=CREATE#
drwxrwxrwx   4 root     root         1024 Jun 28 12:15 /tmp/client#host=balsa#
drwxrwxrwx   3 root     root         1024 Jul  4 11:10 /tmp/client#host=fichte#
drwxrwxrwx   3 root     root         1024 Jun 18 14:18 /tmp/client#host=laerche#
drwxrwxrwx   3 root     root         1024 May 24 13:06 /tmp/client#host=mahagoni#
drwxrwxrwx   3 root     root         1024 Jul  3 10:37 /tmp/client#host=palisander#
drwxrwxrwx   4 root     root         1024 Feb 15 14:57 /tmp/client#host=pcbs10#
drwxrwxrwx   3 root     root         1024 Feb 20 06:43 /tmp/client#host=pcbs11#
lrwxrwxrwx   1 root     root            9 Feb 15 13:58 /usr/X11R6/bin/X#host=pcbs10# -> XF86_SVGA
lrwxrwxrwx   1 root     root            9 Feb 14 17:37 /usr/X11R6/bin/X#host=pcbs11# -> XF86_SVGA
lrwxrwxrwx   1 root     root            7 Feb 14 17:15 /usr/X11R6/bin/X#ktype=diskless# -> XF86_S3
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=balsa#
drwxr-xr-x  23 root     root         1024 Jan 12 14:22 /var#host=eiche#
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=fichte#
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=laerche#
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=mahagoni#
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=palisander#
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=pcbs10#
drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=pcbs11#

Notes: The /tmp directory has an own filesystem on server "eiche",
in order to prevent users from filling the whole filestore (we dont use
quotas). Each client needs a different /tmp because of possible name clashes.
Also, the /var hierarchy is kept differently to prevent any risk, but
that could be optimized perhaps. Note that nfsd and mountd have been
replaced by a script which switches off translations, in the style

-rwxr-xr-x   2 root     root           70 Mar 22 12:54 /usr/sbin/rpc.mountd
-rwxr-xr-x   1 root     root        32772 Jun 11  1995 /usr/sbin/rpc.mountd.notrans
-rwxr-xr-x   2 root     root           70 Mar 22 12:54 /usr/sbin/rpc.nfsd
-rwxr-xr-x   1 root     root        45060 Jun 11  1995 /usr/sbin/rpc.nfsd.notrans

where /usr/sbin/rpc.mountd has the contents

#!/bin/sh
exec /usr/bin/env - NAMETRANS= "`/usr/bin/env`" $0.notrans $*

Of course, that could be improved, but is a quick hack to get things work.

Enjoy,

-- Thomas