aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/pty.c15
-rw-r--r--drivers/char/tty_io.c49
-rw-r--r--drivers/char/vt.c34
-rw-r--r--include/linux/tty.h3
-rw-r--r--include/linux/tty_driver.h6
5 files changed, 65 insertions, 42 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 76b27932d229..ec09c1cd4fe9 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -388,7 +388,14 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
388 return -ENOIOCTLCMD; 388 return -ENOIOCTLCMD;
389} 389}
390 390
391static const struct tty_operations pty_unix98_ops = { 391static void pty_shutdown(struct tty_struct *tty)
392{
393 /* We have our own method as we don't use the tty index */
394 kfree(tty->termios);
395 kfree(tty->termios_locked);
396}
397
398static const struct tty_operations ptm_unix98_ops = {
392 .open = pty_open, 399 .open = pty_open,
393 .close = pty_close, 400 .close = pty_close,
394 .write = pty_write, 401 .write = pty_write,
@@ -397,10 +404,10 @@ static const struct tty_operations pty_unix98_ops = {
397 .chars_in_buffer = pty_chars_in_buffer, 404 .chars_in_buffer = pty_chars_in_buffer,
398 .unthrottle = pty_unthrottle, 405 .unthrottle = pty_unthrottle,
399 .set_termios = pty_set_termios, 406 .set_termios = pty_set_termios,
400 .ioctl = pty_unix98_ioctl 407 .ioctl = pty_unix98_ioctl,
408 .shutdown = pty_shutdown
401}; 409};
402 410
403
404static void __init unix98_pty_init(void) 411static void __init unix98_pty_init(void)
405{ 412{
406 ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); 413 ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
@@ -427,7 +434,7 @@ static void __init unix98_pty_init(void)
427 ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | 434 ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
428 TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; 435 TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
429 ptm_driver->other = pts_driver; 436 ptm_driver->other = pts_driver;
430 tty_set_operations(ptm_driver, &pty_unix98_ops); 437 tty_set_operations(ptm_driver, &ptm_unix98_ops);
431 438
432 pts_driver->owner = THIS_MODULE; 439 pts_driver->owner = THIS_MODULE;
433 pts_driver->driver_name = "pty_slave"; 440 pts_driver->driver_name = "pty_slave";
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 2e96ce0fddc5..f91704d57a4e 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1482,6 +1482,31 @@ release_mem_out:
1482 goto end_init; 1482 goto end_init;
1483} 1483}
1484 1484
1485void tty_free_termios(struct tty_struct *tty)
1486{
1487 struct ktermios *tp;
1488 int idx = tty->index;
1489 /* Kill this flag and push into drivers for locking etc */
1490 if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
1491 /* FIXME: Locking on ->termios array */
1492 tp = tty->termios;
1493 tty->driver->termios[idx] = NULL;
1494 kfree(tp);
1495
1496 tp = tty->termios_locked;
1497 tty->driver->termios_locked[idx] = NULL;
1498 kfree(tp);
1499 }
1500}
1501EXPORT_SYMBOL(tty_free_termios);
1502
1503void tty_shutdown(struct tty_struct *tty)
1504{
1505 tty->driver->ttys[tty->index] = NULL;
1506 tty_free_termios(tty);
1507}
1508EXPORT_SYMBOL(tty_shutdown);
1509
1485/** 1510/**
1486 * release_one_tty - release tty structure memory 1511 * release_one_tty - release tty structure memory
1487 * @kref: kref of tty we are obliterating 1512 * @kref: kref of tty we are obliterating
@@ -1499,27 +1524,11 @@ static void release_one_tty(struct kref *kref)
1499{ 1524{
1500 struct tty_struct *tty = container_of(kref, struct tty_struct, kref); 1525 struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
1501 struct tty_driver *driver = tty->driver; 1526 struct tty_driver *driver = tty->driver;
1502 int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
1503 struct ktermios *tp;
1504 int idx = tty->index;
1505
1506 if (!devpts)
1507 tty->driver->ttys[idx] = NULL;
1508
1509 if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
1510 /* FIXME: Locking on ->termios array */
1511 tp = tty->termios;
1512 if (!devpts)
1513 tty->driver->termios[idx] = NULL;
1514 kfree(tp);
1515
1516 tp = tty->termios_locked;
1517 if (!devpts)
1518 tty->driver->termios_locked[idx] = NULL;
1519 kfree(tp);
1520 }
1521
1522 1527
1528 if (tty->ops->shutdown)
1529 tty->ops->shutdown(tty);
1530 else
1531 tty_shutdown(tty);
1523 tty->magic = 0; 1532 tty->magic = 0;
1524 /* FIXME: locking on tty->driver->refcount */ 1533 /* FIXME: locking on tty->driver->refcount */
1525 tty->driver->refcount--; 1534 tty->driver->refcount--;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index ec94521c3118..37a45db5bae0 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2758,6 +2758,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2758 ret = vc_allocate(currcons); 2758 ret = vc_allocate(currcons);
2759 if (ret == 0) { 2759 if (ret == 0) {
2760 struct vc_data *vc = vc_cons[currcons].d; 2760 struct vc_data *vc = vc_cons[currcons].d;
2761
2762 /* Still being freed */
2763 if (vc->vc_tty) {
2764 release_console_sem();
2765 return -ERESTARTSYS;
2766 }
2761 tty->driver_data = vc; 2767 tty->driver_data = vc;
2762 vc->vc_tty = tty; 2768 vc->vc_tty = tty;
2763 2769
@@ -2787,25 +2793,18 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2787 */ 2793 */
2788static void con_close(struct tty_struct *tty, struct file *filp) 2794static void con_close(struct tty_struct *tty, struct file *filp)
2789{ 2795{
2790 mutex_lock(&tty_mutex); 2796 /* Nothing to do - we defer to shutdown */
2791 acquire_console_sem(); 2797}
2792 if (tty && tty->count == 1) {
2793 struct vc_data *vc = tty->driver_data;
2794 2798
2795 if (vc) 2799static void con_shutdown(struct tty_struct *tty)
2796 vc->vc_tty = NULL; 2800{
2797 tty->driver_data = NULL; 2801 struct vc_data *vc = tty->driver_data;
2798 vcs_remove_sysfs(tty); 2802 BUG_ON(vc == NULL);
2799 release_console_sem(); 2803 acquire_console_sem();
2800 mutex_unlock(&tty_mutex); 2804 vc->vc_tty = NULL;
2801 /* 2805 vcs_remove_sysfs(tty);
2802 * tty_mutex is released, but we still hold BKL, so there is
2803 * still exclusion against init_dev()
2804 */
2805 return;
2806 }
2807 release_console_sem(); 2806 release_console_sem();
2808 mutex_unlock(&tty_mutex); 2807 tty_shutdown(tty);
2809} 2808}
2810 2809
2811static int default_italic_color = 2; // green (ASCII) 2810static int default_italic_color = 2; // green (ASCII)
@@ -2930,6 +2929,7 @@ static const struct tty_operations con_ops = {
2930 .throttle = con_throttle, 2929 .throttle = con_throttle,
2931 .unthrottle = con_unthrottle, 2930 .unthrottle = con_unthrottle,
2932 .resize = vt_resize, 2931 .resize = vt_resize,
2932 .shutdown = con_shutdown
2933}; 2933};
2934 2934
2935int __init vty_init(void) 2935int __init vty_init(void)
diff --git a/include/linux/tty.h b/include/linux/tty.h
index e00393a3d1c9..6e39c705b9b6 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -354,7 +354,8 @@ extern void tty_throttle(struct tty_struct *tty);
354extern void tty_unthrottle(struct tty_struct *tty); 354extern void tty_unthrottle(struct tty_struct *tty);
355extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, 355extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
356 struct winsize *ws); 356 struct winsize *ws);
357 357extern void tty_shutdown(struct tty_struct *tty);
358extern void tty_free_termios(struct tty_struct *tty);
358extern int is_current_pgrp_orphaned(void); 359extern int is_current_pgrp_orphaned(void);
359extern struct pid *tty_get_pgrp(struct tty_struct *tty); 360extern struct pid *tty_get_pgrp(struct tty_struct *tty);
360extern int is_ignored(int sig); 361extern int is_ignored(int sig);
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index ac6e58e26b73..2322313a8589 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -21,6 +21,11 @@
21 * 21 *
22 * Required method. 22 * Required method.
23 * 23 *
24 * void (*shutdown)(struct tty_struct * tty);
25 *
26 * This routine is called when a particular tty device is closed for
27 * the last time freeing up the resources.
28 *
24 * int (*write)(struct tty_struct * tty, 29 * int (*write)(struct tty_struct * tty,
25 * const unsigned char *buf, int count); 30 * const unsigned char *buf, int count);
26 * 31 *
@@ -200,6 +205,7 @@ struct tty_driver;
200struct tty_operations { 205struct tty_operations {
201 int (*open)(struct tty_struct * tty, struct file * filp); 206 int (*open)(struct tty_struct * tty, struct file * filp);
202 void (*close)(struct tty_struct * tty, struct file * filp); 207 void (*close)(struct tty_struct * tty, struct file * filp);
208 void (*shutdown)(struct tty_struct *tty);
203 int (*write)(struct tty_struct * tty, 209 int (*write)(struct tty_struct * tty,
204 const unsigned char *buf, int count); 210 const unsigned char *buf, int count);
205 int (*put_char)(struct tty_struct *tty, unsigned char ch); 211 int (*put_char)(struct tty_struct *tty, unsigned char ch);