Subject: Re: devfs (was Re: Not updating device file inode change times)
To: None <tech-kern@netbsd.org>
From: John F. Woods <jfw@jfwhome.funhouse.com>
List: tech-kern
Date: 09/05/1998 09:25:55
> On Fri, 4 Sep 1998, Todd Vierling wrote:
> [Pipe dream brainstorm]
> Make /dev be mounted dynamically inside the kernel at boot, before init is
> run.  This guarantees the existence of /dev/console, and allows the
> underlying /dev directory to be completely empty.

Eduardo E. Horvath replied:
> Historically, the primary argument against a real devfs /dev is that it
> does not persist across reboots, so any permission changes made to device
> nodes go away.  Solaris decided to go with a standard ufs filesystem with
> a whole bunch of little kernel-grovelling mknod and symlink generators.
> But that has long been a source of problems.
> My original suggestion was that all you need to do is create a devfs
> capable of automagically creating standard device nodes.  unionfs should
> already be capable of doing the rest.  You can chmod something or copy it
> or rename it or delete it.  All we need to do is make sure it works with
> device nodes as well as files, and fix all the annoying unionfs bugs.  

DGUX had an automagically generated /dev directory; their approach to making
permanent changes in permissions and names was to run a script early in /etc/rc
which would make whatever changes the system administrator wanted made.  I
never actually *used* DGUX (just took a course in kernel programming), but
apparently this was regarded as working well enough.

There are, I think, two basic problems that a devfs filesystem can solve
for you:  (1) having to remember to create device nodes before you can use
brand-new hardware (and having to have an up-to-date MAKEDEV script before
doing so), and (2) running with a root filesystem which either has no support
for device nodes (MSDOS) or where said support is tricky (NFS where you'd like
to share a root filesystem between computers with different /dev layouts).

The second problem could potentially be solved with a vnode mount:  specify
a file to be mounted over /dev which would contain a perfectly good UFS
filesystem containing device nodes for the specific computer using it.  The
trouble with that, though, is that you'd need to mount that file before using
any device nodes.  You could overcome that problem by changing the bootstrap
to pass a pathname to the kernel, and adding a shortcut though the vnode mount
code to allow passing the vnode of the file rather than the vnode-device which
is backed by a file.  (Hmm, you don't need a *name* for that vnode device file,
so you could indeed craft a perfectly genuine vnode device file, as long as
you can sneak under the pathname-lookup layer.)  Alternately, you could
structure this as a ramdisk filesystem which the second-level bootstrap would
craft (again, you'd have to change the bootstrap "protocol" to pass some
extra information to the kernel, since now you could have two separate
ramdisks), but then you'd need some scheme to write the contents of the
/dev ramdisk back to the backing file, either in the shutdown script or
periodically (so crashes don't lose (much) information), and the latter case
would require some kind of interlock scheme.  You would also need some way
of telling the second-level bootstrap what file to use, if you want this to
be useful for the NFS case (since each machine would potentially want a
different image file used).

	One thing the UNOS operating system had which I really miss is a
	"configuration file" which got loaded along with the operating system
	and contained run-time values for the kinds of things that NetBSD
	either uses compile-time constants for (ick) or sysctl variables.
	Given something like this, "ah gee I'd have to tell the kernel about
	this at boot time" becomes a trivial problem to solve.

As to the first problem (new devices, brand-new system), the persistent-devfs
above doesn't directly solve it, but may make solutions palatable:  if the
mounted /dev is completely empty, the devfs building code in the kernel would
populate it with a correct initial set of devices; if it's not empty, the
devfs building code might check for emergency problems (/dev/console missing
or wrong, /dev/null has become a regular file), or could validate that the
device names it knows about are all correct (i.e. if sd1c exists, it has the
right device number); whether to have it create new device files depends on
whether you want system administrators to be able to insist on renaming
/dev/sd0e to /dev/user or whether allowing symlinks or hard links is
sufficient.