Major numbers reclaiming for make_dev/MAJOR_AUTO
Stefan Farfeleder
stefan at fafoe.narf.at
Wed Sep 17 08:55:52 PDT 2003
Hi,
attached is a patch that tries to keep track of the major numbers that
were assigned automatically by make_dev() if you use MAJOR_AUTO.
The number of times make_dev() was called with this major number is
stored in the reserved_majors_refcnt array, the entry is decreased again
if you call destroy_dev(). If it reaches zero, the major number is
released by resetting its reserved_majors entry to 0. This avoid the
"Out of major numbers" panic after about 100 make_dev() calls with
MAJOR_AUTO. Majors not assigned by MAJOR_AUTO are not affected. Does
this look reasonable?
Cheers,
Stefan Farfeleder
-------------- next part --------------
Index: src/sys/kern/kern_conf.c
===================================================================
RCS file: /usr/home/ncvs/src/sys/kern/kern_conf.c,v
retrieving revision 1.134
diff -u -r1.134 kern_conf.c
--- src/sys/kern/kern_conf.c 11 Jun 2003 00:56:55 -0000 1.134
+++ src/sys/kern/kern_conf.c 17 Sep 2003 15:40:12 -0000
@@ -46,6 +46,8 @@
/* Built at compile time from sys/conf/majors */
extern unsigned char reserved_majors[256];
+/* Only used for MAJOR_AUTO, 0 otherwise */
+static unsigned int reserved_majors_refcnt[256];
/*
* This is the number of hash-buckets. Experiements with 'real-life'
@@ -294,6 +296,7 @@
KASSERT(i > 0, ("Out of major numbers (%s)", devsw->d_name));
devsw->d_maj = i;
reserved_majors[i] = i;
+ reserved_majors_refcnt[i] = 1;
} else {
if (devsw->d_maj == 256) /* XXX: tty_cons.c is magic */
devsw->d_maj = 0;
@@ -305,6 +308,8 @@
devsw->d_maj);
reserved_majors[devsw->d_maj] = devsw->d_maj;
}
+ if (reserved_majors_refcnt[devsw->d_maj] > 0)
+ reserved_majors_refcnt[devsw->d_maj]++;
}
if (!ready_for_devs) {
@@ -397,6 +402,7 @@
void
destroy_dev(dev_t dev)
{
+ struct cdevsw *d;
if (!(dev->si_flags & SI_NAMED)) {
printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n",
@@ -404,6 +410,11 @@
panic("don't do that");
}
+ d = devsw(dev);
+ if (reserved_majors_refcnt[d->d_maj] > 0)
+ if (--reserved_majors_refcnt[d->d_maj] == 0)
+ reserved_majors[d->d_maj] = 0;
+
devfs_destroy(dev);
if (dev->si_flags & SI_CHILD) {
LIST_REMOVE(dev, si_siblings);
More information about the freebsd-hackers
mailing list