Transname version 1.9 (C) 1997 Thomas Schoebel-Theuer

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

Wherefore is linux-2.0.21-transname.patch?

Currently different diskless clients must 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 replicated
(and maintained separately) just because of the 1% differences.
This duplication causes very large efforts in practise, 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 all clients, not at the server.

Linux transname overcomes this problem by allowing filenames
to be context-dependent. 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 working.

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

Transname 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.

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,
five types of default translations are supported:

 * <name>#host=<hostname>#  depends on the hostname, see "uname -n"
 * <name>#kname=<string>#   works with a hard compiled-in string
 * <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 current translation are displayed at boot time in the kernel messages
for easier debugging, and can be retrieved by reading
/proc/sys/kernel/nametrans which is a special file containing the currently
valid translations.

The default translations change whenever the hostname(1) is set or changed.
Thus, the hostname is not set (or set to the name "(none)") at boot time
before init(8) sets it. So, if you want to use the hostname before that
moment, there are three ways:

 a) set the hostname before via bootp or similar.
 b) use the compiled-in translations kname and ktype solely.
 c) set all translations by lilo (or on the boot command line) with
    kernel parameter   nametrans=#host=banana#:#ktype=diskless# ,
    thus overriding and hiding the default (built-in) translations.

Note that by supplying the colon-separated list of at most 16 suffixes, you
can also use other translation types that are not defined in the default
translations. However, you must ensure that the syntax #...=...# is correct.
The specified contexts will be tried in the specified order *instead* of the
default translations. 

You can override the default (or parameter-supplied) translations at runtime
by executing
echo "#host=$HOST#:#ktype=diskless#:#myconfig=something#" > /proc/sys/kernel/nametrans
However, after doing this (or setting as kernel parameter) the built-in
default translations have no effect any more, thus changing the hostname
will not be reflected in the overridden translations. You can switch
back to the default translations by executing
echo "" > /proc/sys/kernel/nametrans

Another drawback is that administration tools currently are not 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. 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 in turn 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.

Which files you have to make context-dependent will differ for different
needs and different applications. Hopefully some day a standard will
cover the most common cases and the mist common Linux distributions.
A HOWTO on this subject is in preparation.

How to install linux-2.0.21-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, make a kernel with transname support enabled. With "make config"
or "make xconfig", just go to the section "filesystems". Take a look at
the help texts that are associated with the transname 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.

As an example for the changes necessary on our LST-1.8-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 whole /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


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

