diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 43 |
1 files changed, 18 insertions, 25 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index db15f9ba7c0b..bc84e125c6bc 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -1111,9 +1111,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
1111 | * Locks the line discipline as required | 1111 | * Locks the line discipline as required |
1112 | * Writes to the tty driver are serialized by the atomic_write_lock | 1112 | * Writes to the tty driver are serialized by the atomic_write_lock |
1113 | * and are then processed in chunks to the device. The line discipline | 1113 | * and are then processed in chunks to the device. The line discipline |
1114 | * write method will not be involked in parallel for each device | 1114 | * write method will not be invoked in parallel for each device. |
1115 | * The line discipline write method is called under the big | ||
1116 | * kernel lock for historical reasons. New code should not rely on this. | ||
1117 | */ | 1115 | */ |
1118 | 1116 | ||
1119 | static ssize_t tty_write(struct file *file, const char __user *buf, | 1117 | static ssize_t tty_write(struct file *file, const char __user *buf, |
@@ -1213,7 +1211,7 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p) | |||
1213 | * be held until the 'fast-open' is also done. Will change once we | 1211 | * be held until the 'fast-open' is also done. Will change once we |
1214 | * have refcounting in the driver and per driver locking | 1212 | * have refcounting in the driver and per driver locking |
1215 | */ | 1213 | */ |
1216 | struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, | 1214 | static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, |
1217 | struct inode *inode, int idx) | 1215 | struct inode *inode, int idx) |
1218 | { | 1216 | { |
1219 | struct tty_struct *tty; | 1217 | struct tty_struct *tty; |
@@ -1819,8 +1817,10 @@ got_driver: | |||
1819 | /* check whether we're reopening an existing tty */ | 1817 | /* check whether we're reopening an existing tty */ |
1820 | tty = tty_driver_lookup_tty(driver, inode, index); | 1818 | tty = tty_driver_lookup_tty(driver, inode, index); |
1821 | 1819 | ||
1822 | if (IS_ERR(tty)) | 1820 | if (IS_ERR(tty)) { |
1821 | mutex_unlock(&tty_mutex); | ||
1823 | return PTR_ERR(tty); | 1822 | return PTR_ERR(tty); |
1823 | } | ||
1824 | } | 1824 | } |
1825 | 1825 | ||
1826 | if (tty) { | 1826 | if (tty) { |
@@ -2050,7 +2050,6 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2050 | /** | 2050 | /** |
2051 | * tty_do_resize - resize event | 2051 | * tty_do_resize - resize event |
2052 | * @tty: tty being resized | 2052 | * @tty: tty being resized |
2053 | * @real_tty: real tty (not the same as tty if using a pty/tty pair) | ||
2054 | * @rows: rows (character) | 2053 | * @rows: rows (character) |
2055 | * @cols: cols (character) | 2054 | * @cols: cols (character) |
2056 | * | 2055 | * |
@@ -2058,41 +2057,34 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2058 | * peform a terminal resize correctly | 2057 | * peform a terminal resize correctly |
2059 | */ | 2058 | */ |
2060 | 2059 | ||
2061 | int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 2060 | int tty_do_resize(struct tty_struct *tty, struct winsize *ws) |
2062 | struct winsize *ws) | ||
2063 | { | 2061 | { |
2064 | struct pid *pgrp, *rpgrp; | 2062 | struct pid *pgrp; |
2065 | unsigned long flags; | 2063 | unsigned long flags; |
2066 | 2064 | ||
2067 | /* For a PTY we need to lock the tty side */ | 2065 | /* Lock the tty */ |
2068 | mutex_lock(&real_tty->termios_mutex); | 2066 | mutex_lock(&tty->termios_mutex); |
2069 | if (!memcmp(ws, &real_tty->winsize, sizeof(*ws))) | 2067 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) |
2070 | goto done; | 2068 | goto done; |
2071 | /* Get the PID values and reference them so we can | 2069 | /* Get the PID values and reference them so we can |
2072 | avoid holding the tty ctrl lock while sending signals */ | 2070 | avoid holding the tty ctrl lock while sending signals */ |
2073 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2071 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
2074 | pgrp = get_pid(tty->pgrp); | 2072 | pgrp = get_pid(tty->pgrp); |
2075 | rpgrp = get_pid(real_tty->pgrp); | ||
2076 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 2073 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
2077 | 2074 | ||
2078 | if (pgrp) | 2075 | if (pgrp) |
2079 | kill_pgrp(pgrp, SIGWINCH, 1); | 2076 | kill_pgrp(pgrp, SIGWINCH, 1); |
2080 | if (rpgrp != pgrp && rpgrp) | ||
2081 | kill_pgrp(rpgrp, SIGWINCH, 1); | ||
2082 | |||
2083 | put_pid(pgrp); | 2077 | put_pid(pgrp); |
2084 | put_pid(rpgrp); | ||
2085 | 2078 | ||
2086 | tty->winsize = *ws; | 2079 | tty->winsize = *ws; |
2087 | real_tty->winsize = *ws; | ||
2088 | done: | 2080 | done: |
2089 | mutex_unlock(&real_tty->termios_mutex); | 2081 | mutex_unlock(&tty->termios_mutex); |
2090 | return 0; | 2082 | return 0; |
2091 | } | 2083 | } |
2092 | 2084 | ||
2093 | /** | 2085 | /** |
2094 | * tiocswinsz - implement window size set ioctl | 2086 | * tiocswinsz - implement window size set ioctl |
2095 | * @tty; tty | 2087 | * @tty; tty side of tty |
2096 | * @arg: user buffer for result | 2088 | * @arg: user buffer for result |
2097 | * | 2089 | * |
2098 | * Copies the user idea of the window size to the kernel. Traditionally | 2090 | * Copies the user idea of the window size to the kernel. Traditionally |
@@ -2105,17 +2097,16 @@ done: | |||
2105 | * then calls into the default method. | 2097 | * then calls into the default method. |
2106 | */ | 2098 | */ |
2107 | 2099 | ||
2108 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | 2100 | static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) |
2109 | struct winsize __user *arg) | ||
2110 | { | 2101 | { |
2111 | struct winsize tmp_ws; | 2102 | struct winsize tmp_ws; |
2112 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | 2103 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) |
2113 | return -EFAULT; | 2104 | return -EFAULT; |
2114 | 2105 | ||
2115 | if (tty->ops->resize) | 2106 | if (tty->ops->resize) |
2116 | return tty->ops->resize(tty, real_tty, &tmp_ws); | 2107 | return tty->ops->resize(tty, &tmp_ws); |
2117 | else | 2108 | else |
2118 | return tty_do_resize(tty, real_tty, &tmp_ws); | 2109 | return tty_do_resize(tty, &tmp_ws); |
2119 | } | 2110 | } |
2120 | 2111 | ||
2121 | /** | 2112 | /** |
@@ -2540,7 +2531,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2540 | case TIOCGWINSZ: | 2531 | case TIOCGWINSZ: |
2541 | return tiocgwinsz(real_tty, p); | 2532 | return tiocgwinsz(real_tty, p); |
2542 | case TIOCSWINSZ: | 2533 | case TIOCSWINSZ: |
2543 | return tiocswinsz(tty, real_tty, p); | 2534 | return tiocswinsz(real_tty, p); |
2544 | case TIOCCONS: | 2535 | case TIOCCONS: |
2545 | return real_tty != tty ? -EINVAL : tioccons(file); | 2536 | return real_tty != tty ? -EINVAL : tioccons(file); |
2546 | case FIONBIO: | 2537 | case FIONBIO: |
@@ -2785,6 +2776,8 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2785 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 2776 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |
2786 | mutex_init(&tty->atomic_read_lock); | 2777 | mutex_init(&tty->atomic_read_lock); |
2787 | mutex_init(&tty->atomic_write_lock); | 2778 | mutex_init(&tty->atomic_write_lock); |
2779 | mutex_init(&tty->output_lock); | ||
2780 | mutex_init(&tty->echo_lock); | ||
2788 | spin_lock_init(&tty->read_lock); | 2781 | spin_lock_init(&tty->read_lock); |
2789 | spin_lock_init(&tty->ctrl_lock); | 2782 | spin_lock_init(&tty->ctrl_lock); |
2790 | INIT_LIST_HEAD(&tty->tty_files); | 2783 | INIT_LIST_HEAD(&tty->tty_files); |