Subject: Re: CFR: The Auto-Generation Block/Character Device Switch Tables
To: David Laight <>
From: Bill Studenmund <>
List: tech-kern
Date: 05/09/2002 12:45:42
On Thu, 9 May 2002, David Laight wrote:

> > Why? We've always let the routines be global before. Why should we stop
> > that now? Also, with the above change, you're doing more than just change
> > how we handle b/cdevsw, you're forcing anything which calls routines
> > directly to now have to know about major numbers. Also, you're forcing
> > major numbers (for these rare cases) to have to be made global. :-)
> >
> > That strikes me as a bad thing.
> IMHO it means that the symobols don't HAVE to be global.
> In some drivers they will be anyway because the routines will
> be in different source files (unless you do clever things with ld).

True. And that can be an advantage.

> > Just to make sure I understand, compiled-in drivers won't need
> > devsw_attach(), correct?
> My reading was that this would have to be done somewhere.....
> OTOH it could be magiced up by the build process.

I think it needs to be "magiced" up. We have a lot of devices, and to
require every one of them to call devsw_attach(), when we can instead
autogen a config file that has the relevant info, seems wasteful.

> > > const void *devsw_lookup(dev_t dev, enum devswtype type);
> > >
> > > Get a device switch associated with the dev_t 'dev' and the device switch
> > > type 'type'. The 'type' determines which device switches to be looked up.
> > > In the internal of this function, get the major number from 'dev' by using
> > > major() macro. Return the device switch on success. Otherwise, return NULL.
> How many devsw tables do you think there might be?
> In how many places will the 'type' paramter be anything other than
> a constant?
> Seems to me 2 routines would always be faster!
> I presume you have some good reason for not leaving an externally
> visible b/cdevsw[] table (or pointer to table)?

I think the idea is to make the table opaque.

Also, if we ever get around to versioning device drivers to support a
more-flexable minor split (see tech-kern archives from around the 1.3
release, and the "wedges" thread that keeps coming up every now & then),
we will probably have a sparse major numbering scheme in place. So opaque
is good.

> > > int devsw_lookup_major(const void *devsw, enum devswtype type);
> > >
> > > Get a device major number associated with the device switch 'devsw' and
> > > the device switch type 'type'. The 'type' determines which device switches
> > > to be looked up. Return the device switch on success. Otherwise, return NODEV.
> ditto...
> > > dev_t devsw_chr2blk_dev(dev_t chrdev);
> > >
> > > Convert from character dev_t to block dev_t.
> > > Return the valid dev_t (!= NODEV) on success. Otherwise return NODEV.
> > >
> > >
> > > dev_t devsw_blk2chr_dev(dev_t blkdev);
> > >
> > > Convert from block dev_t to character dev_t.
> > > Return the valid dev_t (!= NODEV) on success. Otherwise return NODEV.
> Are these routines possible?
> Esp. if the cdevsw and bdevsw entries are added separately.

See my suggested change to devsw_attach() below. This question is exacly
why I suggested it. :-)

> > > int devsw_attach(const void *devsw, int *maj, enum devswtype type);
> > >
> > > Attach a device switch 'devsw' associated with the major number '*maj'
> > > and the device switch type 'type'. If '*maj' is -1, allocate a major number
> > > dynamically and stored allocated number in '*maj'. Return 0 on success or
> > > an error value.
> >
> > This interface I don't like. You should pass in both the character & block
> > devsws and maj int pointers at once; once call does it all. If you do
> > devsw_attach as two steps (one for character, one for block) how do you
> > know you should assosciate the character & block devices together?
> >
> > I think a better signature would be:
> >
> > int devsw_attach(const cdevsw *cdevsw, int *cret, const bdevsw *bdevsw,
> > 	int *bret)
> I tend to agree.
> However do you want to use 'struct c/bdevsw *' as the argument?
> Would it be better to define a separate (version independant)
> structure that contains the required fields and (esp. for LKM)
> a version number?

Since we're not to the point of having a full DDI-type spec, I think
c/bdevsw is fine.

> This would allow yo to (say) include the information for an
> kernel based /dev at a later time.

Or we can just version the interface (routine name). :-)

> > Don't worry about that. Break them. LKMs are only good for the specific
> > kernel version they were built against. Far less invasive changes have
> > broken lkm compatability in the past. :-)
> Mmmm,,,, Solaris and SVR4 manage to have (resonably) version independant
> LKMs - especially if the guidlines are adhered to properly.
> Makes commercial device drivers much easier.

Well, we're not there yet. :-(

> > One other aspect of lkms now is that they will only load in lkm device
> > slots, bdev_lkm_dummy or cdev_lkm_dummy. It would be nice to retain that
> > behavior. Or at least on a port with N lkm slots, it would be nice for the
> > first N lkms to use them. Otherwise we have problems with adding devices
> > at major numbers for which we don't have device nodes.
> You certainly need to do something here.
> There are 3 sorts of drivers:
> - ones linked into the kernel that MUST have fixed numbers (boot disk etc)
> - ones linked into teh kernel that can have dynamic numbers.
> - dynamically added LKMs that have numbers assigned when installed.
> Since it is generally undesirable to change the number of an installed
> driver - but a kernel rebuild might include a different set of fixed
> drivers - you need to ensure that there is enough space left so that
> dynamically allocated major/minor are in a different part of the
> number space.

I don't believe that the "can have dynamic numbers" category exists, given
that we don't have a /devfs. We *need* a correspondence between a device
and the major number for its nodes in /dev. Dynamic major numbers at
present would break that.

> I would suggest trying to save the device-name to device number
> map somewhere in the root filesystem.  This could be loaded into
> the kernel (probably) before any dynamic assignments are done
> (at least any for optional drivers).  That way /dev wont need
> rebuilding.

Hmmm... That could be interesting. I think that should be a seperate
change, but it could be cool.

Take care,