patch-2.3.10 linux/drivers/char/tty_io.c

Next file: linux/drivers/char/videodev.c
Previous file: linux/drivers/char/tpqic02.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.9/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
@@ -173,13 +173,15 @@
 static int check_tty_count(struct tty_struct *tty, const char *routine)
 {
 #ifdef CHECK_TTY_COUNT
-	struct file *f;
+	struct list_head *p;
 	int count = 0;
 	
-	for(f = inuse_filps; f; f = f->f_next) {
-		if(f->private_data == tty)
+	file_list_lock();
+	for(p = tty->tty_files.next; p != &tty->tty_files; p = p->next) {
+		if(list_entry(p, struct file, f_list)->private_data == tty)
 			count++;
 	}
+	file_list_unlock();
 	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver.subtype == PTY_TYPE_SLAVE &&
 	    tty->link && tty->link->count)
@@ -383,9 +385,9 @@
 void do_tty_hangup(void *data)
 {
 	struct tty_struct *tty = (struct tty_struct *) data;
-	struct file * filp;
 	struct file * cons_filp = NULL;
 	struct task_struct *p;
+	struct list_head *l;
 	int    closecount = 0, n;
 
 	if (!tty)
@@ -395,13 +397,11 @@
 	lock_kernel();
 	
 	check_tty_count(tty, "do_tty_hangup");
-	for (filp = inuse_filps; filp; filp = filp->f_next) {
-		if (filp->private_data != tty)
-			continue;
+	file_list_lock();
+	for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
+		struct file * filp = list_entry(l, struct file, f_list);
 		if (!filp->f_dentry)
 			continue;
-		if (!filp->f_dentry->d_inode)
-			continue;
 		if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV ||
 		    filp->f_dentry->d_inode->i_rdev == SYSCONS_DEV) {
 			cons_filp = filp;
@@ -410,9 +410,10 @@
 		if (filp->f_op != &tty_fops)
 			continue;
 		closecount++;
-		tty_fasync(-1, filp, 0);
+		tty_fasync(-1, filp, 0);	/* can't block */
 		filp->f_op = &hung_up_tty_fops;
 	}
+	file_list_unlock();
 	
 	/* FIXME! What are the locking issues here? This may me overdoing things.. */
 	{
@@ -1307,6 +1308,7 @@
 init_dev_done:
 #endif
 	filp->private_data = tty;
+	file_move(filp, &tty->tty_files);
 	check_tty_count(tty, "tty_open");
 	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver.subtype == PTY_TYPE_MASTER)
@@ -1788,6 +1790,10 @@
  * have to coordinate with the init process, since all processes associated
  * with the current tty must be dead before the new getty is allowed
  * to spawn.
+ *
+ * Now, if it would be correct ;-/ The current code has a nasty hole -
+ * it doesn't catch files in flight. We may send the descriptor to ourselves
+ * via AF_UNIX socket, close it and later fetch from socket. FIXME.
  */
 void do_SAK( struct tty_struct *tty)
 {
@@ -1812,6 +1818,7 @@
 		    ((session > 0) && (p->session == session)))
 			send_sig(SIGKILL, p, 1);
 		else if (p->files) {
+			read_lock(&p->files->file_lock);
 			for (i=0; i < p->files->max_fds; i++) {
 				filp = fcheck_task(p, i);
 				if (filp && (filp->f_op == &tty_fops) &&
@@ -1820,6 +1827,7 @@
 					break;
 				}
 			}
+			read_unlock(&p->files->file_lock);
 		}
 	}
 	read_unlock(&tasklist_lock);
@@ -1937,6 +1945,7 @@
 	tty->tq_hangup.routine = do_tty_hangup;
 	tty->tq_hangup.data = tty;
 	sema_init(&tty->atomic_read, 1);
+	INIT_LIST_HEAD(&tty->tty_files);
 }
 
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)