Subject: Re: Call for review: The New Block/Character Device Switch Configuration Framework
To: None <maekawa@math.sci.kobe-u.ac.jp, matt@3am-software.com>
From: Chris Torek <torek@elf.eng.bsdi.com>
List: tech-kern
Date: 07/01/2001 17:42:28
I still say the Right Answer is to remove the distinction between
block and character device numbers. Note: this does not mean
"remove the distinction between block and character devices". I
mean "remove the distinction between their NUMBERS": block device
#17 will then always correspond to a character device #17, and vice
versa.
This works really well. An inode of type "block device" has a
major and minor number, and an inode of type "character device"
has a major and minor number, and the spec_open() code reads, in
part:
int maj;
struct devsw *dev;
maj = major(dev);
if ((u_int)maj >= ndevsw || (ds = devsw[maj]) == NULL)
return ENXIO;
switch (vp->v_type) {
case VCHR:
...
error = ds->d_open(dev, mode, S_IFCHR, proc);
...
case VBLK:
/*
* Character-only devices have no strategy function.
* This is what distinguishes them from block-and-char.
*/
if (ds->d_strategy == NULL)
return (ENOTBLK);
...
error = ds->d_open(dev, mode, S_IFBLK, proc);
...
}
There is not now, and probably never has been, a device that is
"block-only". Certainly such a thing makes no sense: "blocking"
is simply a behavior imposed upon what would otherwise be a raw
byte stream.
In BSD/OS, we support backwards-compatibility with old (and non-native)
file systems in the ioconf.c.${MACHINE} code. (This depends on the fact
that our dev_t encoding guarantees dv_makedev(1,0,0) > 65535.) The
actual code for devcompat() appears below.
This renumbering simplifies the MAKEDEV scripts and completely
eliminates the nasty goof-up of the form: "ok, I just added my new
zonk-disk driver, #75 and 103 -- `mknod /dev/zonk0c b 75 0 2' and
`newfs zonk0c' ... oops, I just wiped everything out because I gave
it block #75 instead of #103, when they are the other way around ..."
Chris
#ifdef COMPAT_DEV
/*
* Old (and SunOS) block device numbers:
* 7 = /dev/sd* = scsi disk => 17
* 10 = /dev/xd* = "xd" disk => 42
* 11 = /dev/st* = scsi tape => 18
* 16 = /dev/floppy => 54
* 17 = "vd_unused" (SunOS)
* 18 = /dev/sr (SunOS) = our scsi disk
* 19--21 = "vd_unused" (SunOS)
* 22--49 = "id" IPI disks (SunOS)
*/
int
devcompat(dev, ty)
dev_t dev;
int ty;
{
int omaj, omin, unit, part;
/*
* Check for new encoding (major(dev) >= 1). This calls
* /dev/console `old' and maps it, but /dev/console is character
* device <0,0,0>, and 0 maps to 0.
*/
if (major(dev) == 0) {
omaj = dev >> 8;
omin = dev & 0xff;
unit = omin >> 3;
part = omin & 7;
if (ty == VBLK) {
/* Old block numbering */
switch (omaj) {
case 7: /* /dev/sdXX */
dev = dv_makedev(17, unit, part);
break;
#ifdef unneeded
case 10: /* /dev/xdXX -- no drivers */
dev = dv_makedev(42, unit, part);
break;
#endif
case 11: /* /dev/stXX */
dev = makedev(18, omin); /* ??? */
break;
case 16: /* /dev/floppy */
dev = dv_makedev(54, unit, part);
break;
default:
dev = NODEV;
break;
}
} else {
/* Char majors unchanged, but must convert subspecs */
switch (omaj) {
case 17: /* /dev/rsdXX */
#ifdef unneeded
case 42: /* /dev/rxdXX */
#endif
case 54: /* /dev/floppy */
dev = dv_makedev(omaj, unit, part);
break;
default:
dev = makedev(omaj, omin);
break;
}
}
}
return (dev);
}
#endif /* COMPAT_DEV */