From: "H. Peter Anvin" <hpa@zytor.com>


Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/char/tty_io.c |   46 ++++++++++++++++++++++++------------------
 1 files changed, 27 insertions(+), 19 deletions(-)

diff -puN drivers/char/tty_io.c~dynpty-fix drivers/char/tty_io.c
--- 25/drivers/char/tty_io.c~dynpty-fix	Fri May 28 17:01:33 2004
+++ 25-akpm/drivers/char/tty_io.c	Fri May 28 17:01:33 2004
@@ -1068,6 +1068,7 @@ static void release_dev(struct file * fi
 {
 	struct tty_struct *tty, *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
+	int	devpts_master;
 	int	idx;
 	char	buf[64];
 	
@@ -1082,6 +1083,7 @@ static void release_dev(struct file * fi
 	idx = tty->index;
 	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 		      tty->driver->subtype == PTY_TYPE_MASTER);
+	devpts_master = pty_master && (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM);
 	o_tty = tty->link;
 
 #ifdef TTY_PARANOIA_CHECK
@@ -1298,19 +1300,21 @@ static void release_dev(struct file * fi
 		o_tty->ldisc = ldiscs[N_TTY];
 	}
 
+	/*
+	 * The release_mem function takes care of the details of clearing
+	 * the slots and preserving the termios structure.
+	 */
+	release_mem(tty, idx);
+
 #ifdef CONFIG_UNIX98_PTYS
-	if (filp->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,2)) {
+	/* Make this pty number available for reallocation */
+	if (devpts_master) {
 		down(&allocated_ptys_lock);
 		idr_remove(&allocated_ptys, idx);
 		up(&allocated_ptys_lock);
 	}
 #endif
 
-	/* 
-	 * The release_mem function takes care of the details of clearing
-	 * the slots and preserving the termios structure.
-	 */
-	release_mem(tty, idx);
 }
 
 /*
@@ -1330,11 +1334,15 @@ static int tty_open(struct inode * inode
 	struct tty_struct *tty;
 	int noctty, retval;
 	struct tty_driver *driver;
-	int index = -1;
+	int index;
 	dev_t device = inode->i_rdev;
 	unsigned short saved_flags = filp->f_flags;
+
 retry_open:
 	noctty = filp->f_flags & O_NOCTTY;
+	index  = -1;
+	retval = 0;
+
 	if (device == MKDEV(TTYAUX_MAJOR,0)) {
 		if (!current->signal->tty)
 			return -ENXIO;
@@ -1392,22 +1400,20 @@ retry_open:
 			up(&allocated_ptys_lock);
 			return -EIO;
 		}
+		up(&allocated_ptys_lock);
+
 		driver = ptm_driver;
 		retval = init_dev(driver, index, &tty);
 		if (retval) {
+			down(&allocated_ptys_lock);
 			idr_remove(&allocated_ptys, index);
 			up(&allocated_ptys_lock);
 			return retval;
 		}
+
 		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-		if (devpts_pty_new(tty->link)) {
-			/* BADNESS - need to destroy both ptm and pts! */
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-			return -ENOMEM;
-		}
-		up(&allocated_ptys_lock);
-		noctty = 1;
+		if (devpts_pty_new(tty->link))
+			retval = -ENOMEM;
 	} else
 #endif
 	{
@@ -1429,10 +1435,12 @@ got_driver:
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "opening %s...", tty->name);
 #endif
-	if (tty->driver->open)
-		retval = tty->driver->open(tty, filp);
-	else
-		retval = -ENODEV;
+	if (!retval) {
+		if (tty->driver->open)
+			retval = tty->driver->open(tty, filp);
+		else
+			retval = -ENODEV;
+	}
 	filp->f_flags = saved_flags;
 
 	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
_