Index: sys/dev/pty/pty.c =================================================================== --- sys/dev/pty/pty.c +++ sys/dev/pty/pty.c @@ -57,6 +57,11 @@ &pty_warningcnt, 0, "Warnings that will be triggered upon legacy PTY allocation"); +#define MAX_PTY_DEVICES 25600 +static int npty; +SYSCTL_INT(_kern, OID_AUTO, npty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &npty, 0, + "Maximum number of pty devices"); + static int ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp) { @@ -93,34 +98,6 @@ .d_name = "ptydev", }; -static void -pty_clone(void *arg, struct ucred *cr, char *name, int namelen, - struct cdev **dev) -{ - - /* Cloning is already satisfied. */ - if (*dev != NULL) - return; - - /* Only catch /dev/ptyXX. */ - if (namelen != 5 || bcmp(name, "pty", 3) != 0) - return; - - /* Only catch /dev/pty[l-sL-S]X. */ - if (!(name[3] >= 'l' && name[3] <= 's') && - !(name[3] >= 'L' && name[3] <= 'S')) - return; - - /* Only catch /dev/pty[l-sL-S][0-9a-v]. */ - if (!(name[4] >= '0' && name[4] <= '9') && - !(name[4] >= 'a' && name[4] <= 'v')) - return; - - /* Create the controller device node. */ - *dev = make_dev_credf(MAKEDEV_REF, &ptydev_cdevsw, 0, - NULL, UID_ROOT, GID_WHEEL, 0666, "%s", name); -} - static int ptmx_fdopen(struct cdev *dev __unused, int fflags, struct thread *td, struct file *fp) @@ -135,15 +112,58 @@ .d_name = "ptmx", }; +static void +create_pty_devs(void) +{ + int i; + char namedev[6] = "ptyl0"; + + npty = 32; + TUNABLE_INT_FETCH("kern.npty", &npty); + + /* + * Assert that the number of devices requested is less + * than the number of devices we can actually create with + * the current naming scheme. In case the kernel is not + * built with INVARIANTS support, just cap the maximum + * number of devices. + */ + KASSERT(npty <= MAX_PTY_DEVICES, ("Can't create enough devices")); + if (npty > MAX_PTY_DEVICES) + npty = MAX_PTY_DEVICES; + for (i = 0; i < npty; ++i) { + make_dev_credf(MAKEDEV_REF, &ptydev_cdevsw, 0, + NULL, UID_ROOT, GID_WHEEL, 0666, "%s", namedev); + + /* + * Increment the last char in the device name, + */ + namedev[4] += 1; + if (namedev[4] == ('9' + 1)) + namedev[4] = 'a'; + + /* + * We exhausted the range [0-9a-v], let's increment + * the last but one char. + */ + else if (namedev[4] == ('v' + 1)) { + namedev[3] += 1; + namedev[4] = '0'; + if (namedev[3] == ('s' + 1)) + namedev[3] = 'S'; + } + } +} + static int pty_modevent(module_t mod, int type, void *data) { switch(type) { case MOD_LOAD: - EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); make_dev_credf(MAKEDEV_ETERNAL_KLD, &ptmx_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0666, "ptmx"); + create_pty_devs(); break; case MOD_SHUTDOWN: break;