Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Sep 2003 17:55:45 +0200
From:      Stefan Farfeleder <stefan@fafoe.narf.at>
To:        hackers@freebsd.org
Subject:   Major numbers reclaiming for make_dev/MAJOR_AUTO
Message-ID:  <20030917155544.GG697@wombat.fafoe.narf.at>

next in thread | raw e-mail | index | archive | help

--CUfgB8w4ZwR/yMy5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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

--CUfgB8w4ZwR/yMy5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="reserved_majors.diff"

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);

--CUfgB8w4ZwR/yMy5--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030917155544.GG697>