Ira's Diskless 'Winders

This is a collection of informal notes on the subject of getting a
netwinder to boot and mount a large root directory via NFS,
READ-ONLY. By large I mean more than can be run entirely in ram. This is
useful if you want to run a buttload of diskless 'winders.

The concern here is merely on getting them to run, not getting a minimal
install. There are other pages for that. See Mike Montour's, Tim
Potter's pages.
http://www.netwinder.org/~mmontour/
http://www.netwinder.org/~tpot/


-----------------NFS

I won't spend too much time here. Get NFS working. Then get your
/etc/exports file on the NFS server to have a line like this:

/exports/netwinder     babbage(rw, no_root_squash)

where /exports/netwinder is the full linux distribution you want to run
on the client machine (babbage), then say 

exportfs (or send -HUP to rpc.mountd and rpc.nfsd)

I have shamelessly glossed over this, and as punishment you should STOP
reading and go directly to Stan Vardomskiy's Netwinder Rescue HOWTO.
http://www.netwinder.org/~stany/


-----------------DHCP

Network Config on the Client - Here also I won't go into it too much. I
use DHCP, which means all I have to set on the client is netconfig_eth0
dhcp, kernconfig tftp, rootconfig nfs. This means of course that you
need dhcpd on your server. In any case you can find out that stuff
elsewhere. One tip, tail -f /var/log/messages to see what's happening
during boot, and to find out hardware addresses.

----------------KERNEL ISSUES

You need a ramdisk-ready kernel, which means NOT vmlinux.rescue from
netwinder.org. You also need the kernel compiled without root path
specified, which I think means no kernel from netwinder.org. We have
successfully compiled 2.2.2 on the dm 12, using this configuration:
http://www.netwinder.org/~ira/dot_config_arm_2.2.2


----------------MAKING THE IMAGE READ-ONLY---------------

I will assume from this point that you have successfully booted an image
READ-WRITE. Here's how to get a read-only bootable image.

The basic strategy is to mount a ramdisk on the client where whatever
has to be written can be written. For convenience we will use /var, and
symlink any other written-to files into /var. This should be done early
in the boot process, but not too early! Here is what I did first. 

I chose to alter /etc/rc.d/rc.sysinit, since that is where all the
serious mounting and checking goes on. Right after the root directory is
remounted, which is the line:

mount -n -o remount,rw /

I added:

# ADDED TO FACILITATE MULTIPLE NET-BOOTING.
echo "creating RAMDISK for /var..."
dd if=/dev/zero of=/dev/ram2 bs=1k count=4096
mke2fs -v /dev/ram2 4096
rm -rf /var/*
mount -t ext2 /dev/ram2 /var
cp -pRd /var.ro/* /var/.

This will create a 4M ramdisk mounted in the directory /var. Note that
you have to RENAME the real, read-only var to something else like
/var.ro, and create an empty directory called /var in the exported
image:
cd /exports/netwinder
mv var var.ro
mkdir var

There are things that get written in other places like /tmp, so I just
moved the /tmp dir into /var.ro as fake_tmp, and symlinked like so:
mv tmp var.ro/fake_tmp
ln -s var/fake_tmp tmp

This can get tricky because the symlinks point to nothing on the server
machine; they are only valid on the client, after the ramdisk has been
created and mounted.

After you have succeeded in the above, you are ready to try it
read-only. First change the 'rw' in /etc/exports to 'ro':
/exports/netwinder     babbage(ro, no_root_squash)

Then say exportfs, then boot the client. It didn't boot, did it?
Surprise surprise. Mostly it is a matter of studying the init procedure
and taking away any excuse for the damn thing not to boot.

The initialization process goes like this. According to Saddam Hussein,
'init' is the 'Mother of all processes', since it is executed by the
kernel immediately.
1. The 'init' program reads /etc/inittab and does what it says. 
2. One thing inittab says is basically "do sysVinit", which means 
   A. Execute /etc/rc.d/rc.sysinit
   B. Execute the programs pointed to by the symlinks in /etc/rc.d/rc3.d/,
      since 3 is the default runlevel set in inittab,
   C. Execute /etc/rc.d/rc.local 
3. Spawn a bunch of mingettys.

Simple, no? Simple enough for an unemployed programmer to figure out.

Here I will simply recount some things I did to make it boot. I'm
creating a special-purpose machine so I had some leeway in the things I
could throw out. Here is a list of packages that got in the way:
bind
caching-nameserver
gpm
nfs-server
bootparamd
atalk
sysklogd

That last one may give you pause. I don't need it and you probably don't
either if you're bothering with this document. In any case it insists on
CREATING a socket "log" in /dev, which really cheesed me off.

Most of the other problematic actions take place in rc.sysinit or
rc.local. Look for "cp", ">", "rm", etc, all the writing commands, and
either symlink the files or get rid of the action.

Now for the whodunnit: mingetty seems to require a writable filesystem!
Recall that mingettys are spawned from inittab. Here's what I did. I
nuked them. That's right, no console access, but I'm not hooking
monitors to these things anyway. As soon as I commented out these lines,
like so:

# Run gettys in standard runlevels
#1:12345:respawn:/sbin/mingetty tty1
#2:2345:respawn:/sbin/mingetty tty2
#3:2345:respawn:/sbin/mingetty tty3
#4:2345:respawn:/sbin/mingetty tty4
#5:2345:respawn:/sbin/mingetty tty5
#6:2345:respawn:/sbin/mingetty tty6

I was able to boot multiple clients and telnet into them. Whoopee!

Netwinders... taste gooood.



Ira Joseph Woodhead <ira@iatlas.com>