Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Mar 2001 03:49:49 +0100 (CET)
From:      Cyrille Lefevre <clefevre@poboxes.com>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/25866: more than 256 ptys, up to 1302 ptys.
Message-ID:  <200103170249.f2H2nnr03955@gits.dyndns.org>

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

>Number:         25866
>Category:       kern
>Synopsis:       more than 256 ptys, up to 1302 ptys.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 16 18:50:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Cyrille Lefevre
>Release:        FreeBSD 4.3-BETA i386
>Organization:
ACME
>Environment:
System: FreeBSD gits 4.3-BETA FreeBSD 4.3-BETA #18: Sat Mar 17 02:17:40 CET 2001 root@:/disk2/4.x-stable/src/sys/compile/CUSTOM i386

>Description:

	for years, it is not possible to have more than 256 opened ptys
	at a time. this patch deals w/ minor numbers greater than 255 and
	allow up to 1302 ptys to be opened using the following pty names :

	/dev/[pt]ty[p-uw-zP-Z][0-9a-zA-Z]
		      ^^ v cannot be used bcoz it clash w/ the syscons driver.

	same assertion about xyz (Cronyx/Sigma) and R (Rocketport), but
	I suggest to move them to something else since their names aren't
	used internaly by the kernel. something such as efg and h ?

>How-To-Repeat:

	exec sh
	ptyclassnames=pqrstuwxyzPQRSTUVWXYZ
	ptyinstancenames=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
	nptyclass=${#ptyclassnames}
	nptyinstance=${#ptyinstancenames}
	npty=$(($nptyclass*$nptyinstance))
	ofiles=$(($npty*3))
	cat << \EOF > testpty.c
#include <sys/types.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>

int main ()
{
	int i, l = 0;
	int m [npty], s [npty];
	char n [npty][11];

	for (i = 0; i < npty; i++)
		if (openpty (&m [i], &s [i], n [i],
			     (struct termios *)0, (struct winsize *)0) < 0) {
			perror ("openpty");
			fprintf (stderr, "last pty = %d\n", l);
			break;
		} else
			printf ("%d = %s\n", l = i, n [i]);
	for (i = 0; i <= l; i++)
		close (m [i]), close (s [i]);
	return (0);
}
EOF
	make testpty CFLAGS=-Dnpty=$npty LDFLAGS=-lutil
	sysctl -w kern.maxfiles=$ofiles
	sysctl -w kern.maxfilesperproc=$ofiles
	ulimit -n $ofiles
	./testpty > /dev/null
	# should give the following results less the currently opened ptys.
	openpty: No such file or directory
	last pty = 1302

>Fix:

Index: etc/MAKEDEV
===================================================================
RCS file: /home/ncvs/src/etc/MAKEDEV,v
retrieving revision 1.243.2.24
diff -u -r1.243.2.24 MAKEDEV
--- etc/MAKEDEV	2001/03/06 01:40:08	1.243.2.24
+++ etc/MAKEDEV	2001/03/17 02:10:07
@@ -231,6 +231,19 @@
   echo $(((($1 >> 8) << 16) | ($1 % 256)))
 }
 
+# Convert pty (class,instance) to minor number
+# Handle pty minor numbers greater than 256
+ptyminor()
+{
+	echo $(( (( ($1 + $2) &~ 255) << 8) | (($1 + $2) & 255) ))
+}
+
+# *MUST* be the same as in sys/kern/tty_pty.c and lib/libutil/pty.c
+ptyclassnames=pqrstuwxyzPQRSTUVWXYZ
+ptyinstancenames=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+nptyclass=${#ptyclassnames}
+nptyinstance=${#ptyinstancenames}
+
 # Raw partition for disks
 dkrawpart=2
 
@@ -707,34 +720,26 @@
 	done	
 	;;
 pty*)
-	class=`expr $i : 'pty\(.*\)'`
-	case $class in
-	0) offset=0 name=p;;
-	1) offset=32 name=q;;
-	2) offset=64 name=r;;
-	3) offset=96 name=s;;
-# Note that xterm (at least) only look at p-s.
-	4) offset=128 name=P;;
-	5) offset=160 name=Q;;
-	6) offset=192 name=R;;
-	7) offset=224 name=S;;
-	# This still leaves [tuTU].
-	*) echo bad unit for pty in: $i;;
-	esac
 	umask 0
-	case $class in
-	0|1|2|3|4|5|6|7)
+	class=`expr $i : 'pty\(.*\)'`
+	if [ -n "$class" -a "$class" -lt $nptyclass ]; then
+		name=$(echo $ptyclassnames |
+		       dd bs=1 skip=$class count=1 2>/dev/null)
+		offset=$(($class * $nptyintance))
 		i=0
-		while [ $i -lt 32 ]; do
+		while [ $i -lt $nptyintance ]; do
 #			This was an awk substr() before.
-			c=$(echo 0123456789abcdefghijklmnopqrstuv |
+			c=$(echo $ptyinstancenames |
 			    dd bs=1 skip=$i count=1 2>/dev/null)
-			mknod tty$name$c c 5 $(($offset + $i))
-			mknod pty$name$c c 6 $(($offset + $i))
+			minor=$(ptyminor $offset $i)
+			rm -f tty$name$c pty$name$c
+			mknod tty$name$c c 5 $minor
+			mknod pty$name$c c 6 $minor
 			i=$(($i + 1))
 		done
-		;;
-	esac
+	else
+		echo bad unit for pty in: $i
+	fi
 	umask 77
 	;;
 
Index: lib/libutil/pty.c
===================================================================
RCS file: /home/ncvs/src/lib/libutil/pty.c,v
retrieving revision 1.10
diff -u -r1.10 pty.c
--- lib/libutil/pty.c	1999/08/28 00:05:51	1.10
+++ lib/libutil/pty.c	2001/03/17 02:01:06
@@ -53,6 +53,10 @@
 #include <unistd.h>
 #include <libutil.h>
 
+/* *MUST* be the same as in sys/kern/tty_pty.c and etc/MAKEDEV */
+#define ptyclassnames	"pqrstuwxyzPQRSTUVWXYZ"
+#define ptyinstancenames "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
 int
 openpty(amaster, aslave, name, termp, winp)
 	int *amaster, *aslave;
@@ -70,9 +74,9 @@
 	else
 		ttygid = -1;
 
-	for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
+	for (cp1 = ptyclassnames; *cp1; cp1++) {
 		line[8] = *cp1;
-		for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
+		for (cp2 = ptyinstancenames; *cp2; cp2++) {
 			line[5] = 'p';
 			line[9] = *cp2;
 			if ((master = open(line, O_RDWR, 0)) == -1) {
Index: share/man/man4/pty.4
===================================================================
RCS file: /home/ncvs/src/share/man/man4/pty.4,v
retrieving revision 1.8.2.1
diff -u -r1.8.2.1 pty.4
--- share/man/man4/pty.4	2000/12/08 14:59:07	1.8.2.1
+++ share/man/man4/pty.4	2001/03/17 02:01:16
@@ -191,10 +191,10 @@
 is required.
 .El
 .Sh FILES
-.Bl -tag -width /dev/tty[p-sP-S][0-9a-v]x -compact
-.It Pa /dev/pty[p-sP-S][0-9a-v]
+.Bl -tag -width /dev/tty[p-uw-zP-Z][0-9a-zA-Z]x -compact
+.It Pa /dev/pty[p-uw-zP-Z][0-9a-zA-Z]
 master pseudo terminals
-.It Pa /dev/tty[p-sP-S][0-9a-v]
+.It Pa /dev/tty[p-uw-zP-Z][0-9a-zA-Z]
 slave pseudo terminals
 .El
 .Sh DIAGNOSTICS
Index: sys/kern/tty_pty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.74.2.1
diff -u -r1.74.2.1 tty_pty.c
--- sys/kern/tty_pty.c	2001/02/26 04:23:16	1.74.2.1
+++ sys/kern/tty_pty.c	2001/03/17 02:01:41
@@ -129,33 +129,55 @@
 #define	PF_NOSTOP	0x40
 #define PF_UCNTL	0x80		/* user control mode */
 
+/* the opposite of lminor() */
+#define ptyminor(x)	((((x) &~ 255) << 8) | ((x) & 255))
+/* *MUST* be the same as in lib/libutil/pty.c and etc/MAKEDEV */
+#define ptyclassnames	"pqrstuwxyzPQRSTUVWXYZ"
+#define ptyinstancenames "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define nptyclass	(sizeof(ptyclassnames)-1)
+#define nptyinstance	(sizeof(ptyinstancenames)-1)
+#define npty		(nptyclass*nptyinstance)
+
 /*
  * This function creates and initializes a pts/ptc pair
+ *
+ * pts == /dev/tty[p-uw-zP-Z][0-9a-zA-Z]
+ * ptc == /dev/pty[p-uw-zP-Z][0-9a-zA-Z]
  *
- * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
- * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
+ * don't use the "v" master/slave pair bcoz it clash w/ the syscons driver.
+ * same assertion about the less used Cronyx/Sigma (xyz) and Rocketport (R)
+ * drivers.
  *
- * XXX: define and add mapping of upper minor bits to allow more 
- *      than 256 ptys.
  */
 static void
 ptyinit(n)
 	int n;
 {
 	dev_t devs, devc;
-	char *names = "pqrsPQRS";
+	char *classes = ptyclassnames;
+	char *instances = ptyinstancenames;
 	struct pt_ioctl *pt;
 
-	/* For now we only map the lower 8 bits of the minor */
-	if (n & ~0xff)
+#ifdef notdef
+	if (bootverbose)
+		printf ("ptyinit: n(%d) <= %d\n", n, npty);
+#endif
+	/* be safe */
+	if (n >= npty)
 		return;
-
+#ifdef notdef
+	if (bootverbose)
+		printf ("ptyinit: makedev([tp]ty%c%c)\n",
+			classes[n / nptyinstance], instances[n % nptyinstance]);
+#endif
 	pt = malloc(sizeof(*pt), M_PTY, M_WAITOK);
 	bzero(pt, sizeof(*pt));
-	pt->devs = devs = make_dev(&pts_cdevsw, n,
-	    0, 0, 0666, "tty%c%r", names[n / 32], n % 32);
-	pt->devc = devc = make_dev(&ptc_cdevsw, n,
-	    0, 0, 0666, "pty%c%r", names[n / 32], n % 32);
+	pt->devs = devs = make_dev(&pts_cdevsw, ptyminor(n),
+	    0, 0, 0666, "tty%c%c",
+	    classes[n / nptyinstance], instances[n % nptyinstance]);
+	pt->devc = devc = make_dev(&ptc_cdevsw, ptyminor(n),
+	    0, 0, 0666, "pty%c%c",
+	    classes[n / nptyinstance], instances[n % nptyinstance]);
 
 	devs->si_drv1 = devc->si_drv1 = pt;
 	devs->si_tty = devc->si_tty = &pt->pt_tty;
@@ -171,7 +193,7 @@
 {
 	register struct tty *tp;
 	int error;
-	int minr;
+	int minr, nextminr;
 	dev_t nextdev;
 	struct pt_ioctl *pti;
 
@@ -181,14 +203,19 @@
 	 * next one too, so people can open it.
 	 */
 	minr = lminor(dev);
-	if (minr < 255) {
-		nextdev = makedev(major(dev), minr + 1);
-		if (!nextdev->si_drv1) {
-			ptyinit(minr + 1);
-		}
+	nextminr = minr+1;
+	if (nextminr < npty) {
+		nextdev = makedev(major(dev), ptyminor(nextminr));
+		if (!nextdev->si_drv1)
+			ptyinit(nextminr);
 	}
 	if (!dev->si_drv1)
-		ptyinit(minor(dev));
+		ptyinit(minr);
+#ifdef notdef
+	if (bootverbose)
+		printf ("ptyopen: makedev(%d:%#x)\n",
+			major(dev), ptyminor(minr));
+#endif
 	if (!dev->si_drv1)
 		return(ENXIO);	
 	pti = dev->si_drv1;
@@ -351,9 +378,9 @@
 	struct pt_ioctl *pti;
 
 	if (!dev->si_drv1)
-		ptyinit(minor(dev));
+		ptyinit(lminor(dev));
 	if (!dev->si_drv1)
-		return(ENXIO);	
+		return(ENXIO);
 	tp = dev->si_tty;
 	if (tp->t_oproc)
 		return (EIO);
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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