Subject: Re: 32 bit dev_t
To: None <tech-kern@NetBSD.ORG>
From: Charles M. Hannum <mycroft@mit.edu>
List: tech-kern
Date: 01/13/1998 08:31:10
A few comments:

* As an alternative to renumbering, you could instead make the minor
number non-contiguous; i.e.:

    3322222222221111111111
    10987654321098765432109876543210
    |--minor---||--major---||minor-|    new
                    |major-||minor-|    old

* Given the above scheme, should we decide to renumber everything at
some point (hopefully only once!!!), we can simply choose some portion
of the major numbers (say, the first 256) and use them for
`compatibility'.  There's no need to waste half the number space.

* If you're going to change all the existing device numbers, rather
than turning major() and minor() into functions, you should do any
old->new conversion (if necessary) in checkalias(), before it's put in
v_specinfo.  This value is *only* used internally to the kernel.
(You'll note that the device number returned by *stat(2) is taken
directly from the file system through *_getattr().)  You could even
make it call some machine-dependent function to do the mapping, or use
a conversion table like what Chris suggested.  There's no reason the
rest of the kernel has to know about different numbering schemes, so
don't tell it; you'll just end up making the kernel larger and slower.
(Think about what you're proposing doing to your serial port read()
path, for example.  A couple of calls to major(), one to minor(), etc.
How many more layers of indirection before you make it slow enough
that nobody wants to use it any more?)

[* In fact, if you were really slick, you could have checkalias()
munge my non-contiguous minor numbers into contiguous ones for use
inside the kernel, so you can do simple bit-shifting elsewhere.  Uses
of major(), minor() and makedev() outside the kernel are so rare that
it doesn't matter if they're a little slower.  You get complete
compatibility with no measurable performance penalty.  But this may be
degenerating into silliness.]

* There's no reason to worry about the size of cdevsw[].  If nothing
else, we can do something we arguably should have done years ago: put
the individual cdevsw[] entries in the drivers themselves and just
have cdevsw[] be an array of pointers.  The entry points aren't really
anyone's business but the driver anyway.  (Note that I'm *not*
suggesting we have the driver `register' it.  HTF do you tell the
driver to do that, and where would it get its major number from,
anyway?)

* We can't have stat(2) or mknod(2) magically change device numbers
behind our back.  For example, consider using pax(1) to pack or unpack
a file system used by another operating system.  Total lossage.  This
is exactly the sort of thing that makes me consider tossing the
computer off a tall building.  Note that this is *not* a problem for
ttyname(3); when it fstat(2)s the file descriptor and stat(2)s the
device node, it will get the same info, so it will just work.

* You can't have perfect compatibility with 16-bit device numbers;
it's not even *possible* in all cases.  The whole point of this
exercise is to be able to use more device numbers, and once you've
used more than 2^16, you're screwed.  That said, you could probably do
better.


In short:

Ignoring funky interfaces to mknod(8), you could do the entire change
to 12/20 device numbers by touching <20 lines of code.  Why add hair
where you don't need it?