Subject: Re: The new rc.d stuff...
To: None <frank@wins.uva.nl>
From: William O Ferry <woferry@iname.com>
List: current-users
Date: 03/28/2000 22:47:39
Frank van der Linden wrote:
> It's the old problem of "which filesystems are mounted and from where".
> dhclient wants /var/run, and /var may be mounted over the network.
> However, if you use dhclient, you may want to use dhclient itself
> to get on the network, so you're running around in circles.
>
> Right now, the dhclient script assumes that /var may be mounted over
> the network, so that lands it one of the last positions in the
> startup order, since that makes it depend on some filesystems
> being mounted, and the network having been brought up. Which
> is not what you want.

	As was also pointed out by Robert Elz, dhclient is rather useless once
you have networking started, so it seems a bad assumption to make.  Even
if it did write to a nfs-mounted /var chances are that mount got
clobbered by dhclient changing the network interface.  In my experience
having networking enabled before running dhclient only spells disaster,
even when netbooting where everything was set correctly and dhclient
doesn't have to change anything (and in this kind of case what's the
sense in running dhclient?)

	Plus, our own default /etc/rc.conf specifies that /var is a "beforenet"
filesystem.  So part of our default setup requires that /var is NOT a
network filesystem and another part assumes that it will be?  If the
user is going to make this kind of change to rc.conf (and I'd guess most
people don't, personally I either NFS-mount / or none of the "critical"
filesystems) they can make the changes in the script ordering too.

	Before /etc/rc.d, both dhclient and pppd were executed in a place where
they worked correctly to set up the network interfaces at basically the
same time it would have been set up if they were done manually.  Now
they have both been moved beyond most of the daemons that require
networking, making them quite unusable.

	I'd propose taking the /etc/rc.d/network script and splitting it up
into smaller chunks, much like what was done with /etc/rc.  Right now
basically all that happened was to rip out the ipfilter, ipnat, dhclient
and pppd code, and add shutdown support.  I took a stab at splitting it
up and came up with the following groups (in the order they were run in
the old /etc/netstart script):

hostname (sets hostname and domainname, should these be separate?)
flushroute (obvious)
ipfilter
ifconfig (initializes localhost and other interfaces)
gateway (does route add default, maybe should be called defaultroute?)
ifalias (obvious)
ipnat
ppp
dhclient
ipv6 (obvious)
NETWORK (dummy dependency, depends on everything above, and also takes
care of /etc/netstart.local until it's phased out)

	I've been using this on my machines for a week or so now, and it's
worked quite well.  I'd be happy to send-pr this if it sounds decent. 
It's also shown me my biggest headaches with this rc.d implementation. 
First off while the ordering works well once you have it dialed in,
setting the order can be a major PITA.  It took several hours of dialing
things in, scripts would mysteriously jump to the top of the list even
though they depended on other things, and others seemed to want to stay
at the end even when I didn't want them there.  With the old /etc/rc it
would have been a simple matter of moving blocks of text around, and
with an init.d/rc.d scheme it would have been just renaming a file.  In
my case since I wanted to insert something between the network script
and everything that depends on network, I had to edit 6 or 7 separate
files to get the dependencies right (which is why I gave up on network
and went with the NETWORK dummy dependency).  Plus, since the files in
/etc/rc.d are files and not symlinks, if you edit any of these files
with an editor that automatically backs up the files, you end up with
two copies of the script in the directory and things get started or
stopped twice.  In the init.d/rc.d scheme the backups (by my experience)
go to the init.d directory where the actual files are, so there aren't
any extraneous files in rc.d.  

	As a suggestion (that might make the ordering easier), would it be
possible to change the meaning of BEFORE: and add an AFTER: condition? 
It would make the most sense to me if BEFORE: tried to put something
*IMMEDIATELY* before the named file, and if AFTER: put it immediately
afterwards.  This would have made inserting something like what I wanted
simple, if I could have just said "# AFTER: network", and it ensured
that it runs before anything with "# REQUIRE: network" (obviously if
there are multiple files requiring to be AFTER something the order would
either be arbitrary or based on the other dependencies.  Then I wouldn't
have had to modify a half-dozen other files to insert my script. 
Similarly at the moment if you specify a file with just a BEFORE:
condition it seems to slam it to the top of the list.  If I wanted that
I could have just said "# BEFORE: raidframe" or whatever comes out top
in the rcorder list.  Being able to insert something directly before
something else would allow you to just create the new file and set the
BEFORE: condition, and not have to alter the file you're trying to
precede to make it depend on the new file.  I think it would reduce the
number of times you have to edit the stock NetBSD scripts to insert your
own scripts somewhere in the process.  For things such as the atalkd
script depending on xdm, maybe a FIRST: and LAST: condition (or dummy
dependies of the same name?) would also be useful (and atalkd could have
just specified "# LAST:").

	All in all, I think there's definite promise.  When it works it works
well (other than being painfully slow on a slower SPARC or DECstation or
the like, it seems NetBSD isn't far from requiring a 200MHz CPU to boot
in any reasonable amount of time).  When anything goes wrong (and
unfortunately things are broken by default now as far as ppp and
dhclient is concerned, so it's "wrong" right out of the box) trying to
sort out the pieces and put things back together is a massive
undertaking.  And I've already added /etc/rc.pkg.d and /etc/rc.local.d
to my setup, and it's working great.

	By the way, I know this approaches the runlevel issue (and I'm trying
not to go there, I don't like it either..  =), but are there any
thoughts on having the dependencies evaluated on execution of a script,
so that say by my above example I'd do an "/etc/rc.d/NETWORK start" and
it would start everything NETWORK depends on?  Obviously it wouldn't
work the other way around (i.e. NETWORK stop would only stop the NETWORK
script, and maybe what's after it, but it's not intuitive).

	From my interactions with the scripts, I'd also suggest changing the
current behavior from having /etc/rc do "start" to doing a "querystart"
or whatever you'd want to call a conditional start.  For example if I
say "/etc/rc.d/rwho start" I think I really want it to start, even if
rc.conf says "NO".  IMHO only /etc/rc should actually check the yes/no
for the script, if the command is run manually it shouldn't matter what
the rcvar says, I shouldn't have to say "force".

	Thanks (and apologies for the long message).
                                                  Will