diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:43:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:36 -0500 |
commit | fc6f6238226e6d1248e1967eae2bf556eaf3ac17 (patch) | |
tree | 07cef0fafd30bd622dac1db4751e10734773c863 | |
parent | a47d545f5782cbde871b50bdf4a83379ed2da222 (diff) |
pty: simplify resize
We have special case logic for resizing pty/tty pairs. We also have a per
driver resize method so for the pty case we should use it.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/char/hvc_console.c | 2 | ||||
-rw-r--r-- | drivers/char/pty.c | 54 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 31 | ||||
-rw-r--r-- | drivers/char/vt.c | 14 | ||||
-rw-r--r-- | include/linux/tty.h | 3 | ||||
-rw-r--r-- | include/linux/tty_driver.h | 6 |
6 files changed, 74 insertions, 36 deletions
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 0587b66d6fc7..5a8a4c28c867 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -529,7 +529,7 @@ static void hvc_set_winsz(struct work_struct *work) | |||
529 | tty = tty_kref_get(hp->tty); | 529 | tty = tty_kref_get(hp->tty); |
530 | spin_unlock_irqrestore(&hp->lock, hvc_flags); | 530 | spin_unlock_irqrestore(&hp->lock, hvc_flags); |
531 | 531 | ||
532 | tty_do_resize(tty, tty, &ws); | 532 | tty_do_resize(tty, &ws); |
533 | tty_kref_put(tty); | 533 | tty_kref_put(tty); |
534 | } | 534 | } |
535 | 535 | ||
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 6d4582712b1f..b5daaaa9007e 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -230,6 +230,55 @@ static void pty_set_termios(struct tty_struct *tty, | |||
230 | tty->termios->c_cflag |= (CS8 | CREAD); | 230 | tty->termios->c_cflag |= (CS8 | CREAD); |
231 | } | 231 | } |
232 | 232 | ||
233 | /** | ||
234 | * pty_do_resize - resize event | ||
235 | * @tty: tty being resized | ||
236 | * @real_tty: real tty (not the same as tty if using a pty/tty pair) | ||
237 | * @rows: rows (character) | ||
238 | * @cols: cols (character) | ||
239 | * | ||
240 | * Update the termios variables and send the neccessary signals to | ||
241 | * peform a terminal resize correctly | ||
242 | */ | ||
243 | |||
244 | int pty_resize(struct tty_struct *tty, struct winsize *ws) | ||
245 | { | ||
246 | struct pid *pgrp, *rpgrp; | ||
247 | unsigned long flags; | ||
248 | struct tty_struct *pty = tty->link; | ||
249 | |||
250 | /* For a PTY we need to lock the tty side */ | ||
251 | mutex_lock(&tty->termios_mutex); | ||
252 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) | ||
253 | goto done; | ||
254 | |||
255 | /* Get the PID values and reference them so we can | ||
256 | avoid holding the tty ctrl lock while sending signals. | ||
257 | We need to lock these individually however. */ | ||
258 | |||
259 | spin_lock_irqsave(&tty->ctrl_lock, flags); | ||
260 | pgrp = get_pid(tty->pgrp); | ||
261 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
262 | |||
263 | spin_lock_irqsave(&pty->ctrl_lock, flags); | ||
264 | rpgrp = get_pid(pty->pgrp); | ||
265 | spin_unlock_irqrestore(&pty->ctrl_lock, flags); | ||
266 | |||
267 | if (pgrp) | ||
268 | kill_pgrp(pgrp, SIGWINCH, 1); | ||
269 | if (rpgrp != pgrp && rpgrp) | ||
270 | kill_pgrp(rpgrp, SIGWINCH, 1); | ||
271 | |||
272 | put_pid(pgrp); | ||
273 | put_pid(rpgrp); | ||
274 | |||
275 | tty->winsize = *ws; | ||
276 | pty->winsize = *ws; /* Never used so will go away soon */ | ||
277 | done: | ||
278 | mutex_unlock(&tty->termios_mutex); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
233 | static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | 282 | static int pty_install(struct tty_driver *driver, struct tty_struct *tty) |
234 | { | 283 | { |
235 | struct tty_struct *o_tty; | 284 | struct tty_struct *o_tty; |
@@ -290,6 +339,7 @@ static const struct tty_operations pty_ops = { | |||
290 | .chars_in_buffer = pty_chars_in_buffer, | 339 | .chars_in_buffer = pty_chars_in_buffer, |
291 | .unthrottle = pty_unthrottle, | 340 | .unthrottle = pty_unthrottle, |
292 | .set_termios = pty_set_termios, | 341 | .set_termios = pty_set_termios, |
342 | .resize = pty_resize | ||
293 | }; | 343 | }; |
294 | 344 | ||
295 | /* Traditional BSD devices */ | 345 | /* Traditional BSD devices */ |
@@ -319,6 +369,7 @@ static const struct tty_operations pty_ops_bsd = { | |||
319 | .unthrottle = pty_unthrottle, | 369 | .unthrottle = pty_unthrottle, |
320 | .set_termios = pty_set_termios, | 370 | .set_termios = pty_set_termios, |
321 | .ioctl = pty_bsd_ioctl, | 371 | .ioctl = pty_bsd_ioctl, |
372 | .resize = pty_resize | ||
322 | }; | 373 | }; |
323 | 374 | ||
324 | static void __init legacy_pty_init(void) | 375 | static void __init legacy_pty_init(void) |
@@ -561,7 +612,8 @@ static const struct tty_operations ptm_unix98_ops = { | |||
561 | .unthrottle = pty_unthrottle, | 612 | .unthrottle = pty_unthrottle, |
562 | .set_termios = pty_set_termios, | 613 | .set_termios = pty_set_termios, |
563 | .ioctl = pty_unix98_ioctl, | 614 | .ioctl = pty_unix98_ioctl, |
564 | .shutdown = pty_unix98_shutdown | 615 | .shutdown = pty_unix98_shutdown, |
616 | .resize = pty_resize | ||
565 | }; | 617 | }; |
566 | 618 | ||
567 | static const struct tty_operations pty_unix98_ops = { | 619 | static const struct tty_operations pty_unix98_ops = { |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 2a15af65dd11..d33e5ab06177 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -2048,7 +2048,6 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2048 | /** | 2048 | /** |
2049 | * tty_do_resize - resize event | 2049 | * tty_do_resize - resize event |
2050 | * @tty: tty being resized | 2050 | * @tty: tty being resized |
2051 | * @real_tty: real tty (not the same as tty if using a pty/tty pair) | ||
2052 | * @rows: rows (character) | 2051 | * @rows: rows (character) |
2053 | * @cols: cols (character) | 2052 | * @cols: cols (character) |
2054 | * | 2053 | * |
@@ -2056,41 +2055,34 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2056 | * peform a terminal resize correctly | 2055 | * peform a terminal resize correctly |
2057 | */ | 2056 | */ |
2058 | 2057 | ||
2059 | int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 2058 | int tty_do_resize(struct tty_struct *tty, struct winsize *ws) |
2060 | struct winsize *ws) | ||
2061 | { | 2059 | { |
2062 | struct pid *pgrp, *rpgrp; | 2060 | struct pid *pgrp; |
2063 | unsigned long flags; | 2061 | unsigned long flags; |
2064 | 2062 | ||
2065 | /* For a PTY we need to lock the tty side */ | 2063 | /* Lock the tty */ |
2066 | mutex_lock(&real_tty->termios_mutex); | 2064 | mutex_lock(&tty->termios_mutex); |
2067 | if (!memcmp(ws, &real_tty->winsize, sizeof(*ws))) | 2065 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) |
2068 | goto done; | 2066 | goto done; |
2069 | /* Get the PID values and reference them so we can | 2067 | /* Get the PID values and reference them so we can |
2070 | avoid holding the tty ctrl lock while sending signals */ | 2068 | avoid holding the tty ctrl lock while sending signals */ |
2071 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2069 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
2072 | pgrp = get_pid(tty->pgrp); | 2070 | pgrp = get_pid(tty->pgrp); |
2073 | rpgrp = get_pid(real_tty->pgrp); | ||
2074 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 2071 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
2075 | 2072 | ||
2076 | if (pgrp) | 2073 | if (pgrp) |
2077 | kill_pgrp(pgrp, SIGWINCH, 1); | 2074 | kill_pgrp(pgrp, SIGWINCH, 1); |
2078 | if (rpgrp != pgrp && rpgrp) | ||
2079 | kill_pgrp(rpgrp, SIGWINCH, 1); | ||
2080 | |||
2081 | put_pid(pgrp); | 2075 | put_pid(pgrp); |
2082 | put_pid(rpgrp); | ||
2083 | 2076 | ||
2084 | tty->winsize = *ws; | 2077 | tty->winsize = *ws; |
2085 | real_tty->winsize = *ws; | ||
2086 | done: | 2078 | done: |
2087 | mutex_unlock(&real_tty->termios_mutex); | 2079 | mutex_unlock(&tty->termios_mutex); |
2088 | return 0; | 2080 | return 0; |
2089 | } | 2081 | } |
2090 | 2082 | ||
2091 | /** | 2083 | /** |
2092 | * tiocswinsz - implement window size set ioctl | 2084 | * tiocswinsz - implement window size set ioctl |
2093 | * @tty; tty | 2085 | * @tty; tty side of tty |
2094 | * @arg: user buffer for result | 2086 | * @arg: user buffer for result |
2095 | * | 2087 | * |
2096 | * Copies the user idea of the window size to the kernel. Traditionally | 2088 | * Copies the user idea of the window size to the kernel. Traditionally |
@@ -2103,17 +2095,16 @@ done: | |||
2103 | * then calls into the default method. | 2095 | * then calls into the default method. |
2104 | */ | 2096 | */ |
2105 | 2097 | ||
2106 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | 2098 | static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) |
2107 | struct winsize __user *arg) | ||
2108 | { | 2099 | { |
2109 | struct winsize tmp_ws; | 2100 | struct winsize tmp_ws; |
2110 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | 2101 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) |
2111 | return -EFAULT; | 2102 | return -EFAULT; |
2112 | 2103 | ||
2113 | if (tty->ops->resize) | 2104 | if (tty->ops->resize) |
2114 | return tty->ops->resize(tty, real_tty, &tmp_ws); | 2105 | return tty->ops->resize(tty, &tmp_ws); |
2115 | else | 2106 | else |
2116 | return tty_do_resize(tty, real_tty, &tmp_ws); | 2107 | return tty_do_resize(tty, &tmp_ws); |
2117 | } | 2108 | } |
2118 | 2109 | ||
2119 | /** | 2110 | /** |
@@ -2538,7 +2529,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2538 | case TIOCGWINSZ: | 2529 | case TIOCGWINSZ: |
2539 | return tiocgwinsz(real_tty, p); | 2530 | return tiocgwinsz(real_tty, p); |
2540 | case TIOCSWINSZ: | 2531 | case TIOCSWINSZ: |
2541 | return tiocswinsz(tty, real_tty, p); | 2532 | return tiocswinsz(real_tty, p); |
2542 | case TIOCCONS: | 2533 | case TIOCCONS: |
2543 | return real_tty != tty ? -EINVAL : tioccons(file); | 2534 | return real_tty != tty ? -EINVAL : tioccons(file); |
2544 | case FIONBIO: | 2535 | case FIONBIO: |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 639e126b2bff..80014213fb53 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -819,8 +819,8 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, | |||
819 | * ctrl_lock of the tty IFF a tty is passed. | 819 | * ctrl_lock of the tty IFF a tty is passed. |
820 | */ | 820 | */ |
821 | 821 | ||
822 | static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 822 | static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, |
823 | struct vc_data *vc, unsigned int cols, unsigned int lines) | 823 | unsigned int cols, unsigned int lines) |
824 | { | 824 | { |
825 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 825 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
826 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 826 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; |
@@ -932,7 +932,7 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | |||
932 | ws.ws_row = vc->vc_rows; | 932 | ws.ws_row = vc->vc_rows; |
933 | ws.ws_col = vc->vc_cols; | 933 | ws.ws_col = vc->vc_cols; |
934 | ws.ws_ypixel = vc->vc_scan_lines; | 934 | ws.ws_ypixel = vc->vc_scan_lines; |
935 | tty_do_resize(tty, real_tty, &ws); | 935 | tty_do_resize(tty, &ws); |
936 | } | 936 | } |
937 | 937 | ||
938 | if (CON_IS_VISIBLE(vc)) | 938 | if (CON_IS_VISIBLE(vc)) |
@@ -954,13 +954,12 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | |||
954 | 954 | ||
955 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | 955 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) |
956 | { | 956 | { |
957 | return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows); | 957 | return vc_do_resize(vc->vc_tty, vc, cols, rows); |
958 | } | 958 | } |
959 | 959 | ||
960 | /** | 960 | /** |
961 | * vt_resize - resize a VT | 961 | * vt_resize - resize a VT |
962 | * @tty: tty to resize | 962 | * @tty: tty to resize |
963 | * @real_tty: tty if a pty/tty pair | ||
964 | * @ws: winsize attributes | 963 | * @ws: winsize attributes |
965 | * | 964 | * |
966 | * Resize a virtual terminal. This is called by the tty layer as we | 965 | * Resize a virtual terminal. This is called by the tty layer as we |
@@ -971,14 +970,13 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | |||
971 | * termios_mutex and the tty ctrl_lock in that order. | 970 | * termios_mutex and the tty ctrl_lock in that order. |
972 | */ | 971 | */ |
973 | 972 | ||
974 | int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 973 | int vt_resize(struct tty_struct *tty, struct winsize *ws) |
975 | struct winsize *ws) | ||
976 | { | 974 | { |
977 | struct vc_data *vc = tty->driver_data; | 975 | struct vc_data *vc = tty->driver_data; |
978 | int ret; | 976 | int ret; |
979 | 977 | ||
980 | acquire_console_sem(); | 978 | acquire_console_sem(); |
981 | ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row); | 979 | ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row); |
982 | release_console_sem(); | 980 | release_console_sem(); |
983 | return ret; | 981 | return ret; |
984 | } | 982 | } |
diff --git a/include/linux/tty.h b/include/linux/tty.h index dfc77ded198a..f88169787a5f 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -360,8 +360,7 @@ extern int tty_write_room(struct tty_struct *tty); | |||
360 | extern void tty_driver_flush_buffer(struct tty_struct *tty); | 360 | extern void tty_driver_flush_buffer(struct tty_struct *tty); |
361 | extern void tty_throttle(struct tty_struct *tty); | 361 | extern void tty_throttle(struct tty_struct *tty); |
362 | extern void tty_unthrottle(struct tty_struct *tty); | 362 | extern void tty_unthrottle(struct tty_struct *tty); |
363 | extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 363 | extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); |
364 | struct winsize *ws); | ||
365 | extern void tty_shutdown(struct tty_struct *tty); | 364 | extern void tty_shutdown(struct tty_struct *tty); |
366 | extern void tty_free_termios(struct tty_struct *tty); | 365 | extern void tty_free_termios(struct tty_struct *tty); |
367 | extern int is_current_pgrp_orphaned(void); | 366 | extern int is_current_pgrp_orphaned(void); |
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 78416b901589..08e088334dba 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h | |||
@@ -196,8 +196,7 @@ | |||
196 | * Optional: If not provided then the write method is called under | 196 | * Optional: If not provided then the write method is called under |
197 | * the atomic write lock to keep it serialized with the ldisc. | 197 | * the atomic write lock to keep it serialized with the ldisc. |
198 | * | 198 | * |
199 | * int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, | 199 | * int (*resize)(struct tty_struct *tty, struct winsize *ws) |
200 | * unsigned int rows, unsigned int cols); | ||
201 | * | 200 | * |
202 | * Called when a termios request is issued which changes the | 201 | * Called when a termios request is issued which changes the |
203 | * requested terminal geometry. | 202 | * requested terminal geometry. |
@@ -258,8 +257,7 @@ struct tty_operations { | |||
258 | int (*tiocmget)(struct tty_struct *tty, struct file *file); | 257 | int (*tiocmget)(struct tty_struct *tty, struct file *file); |
259 | int (*tiocmset)(struct tty_struct *tty, struct file *file, | 258 | int (*tiocmset)(struct tty_struct *tty, struct file *file, |
260 | unsigned int set, unsigned int clear); | 259 | unsigned int set, unsigned int clear); |
261 | int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, | 260 | int (*resize)(struct tty_struct *tty, struct winsize *ws); |
262 | struct winsize *ws); | ||
263 | int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); | 261 | int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); |
264 | #ifdef CONFIG_CONSOLE_POLL | 262 | #ifdef CONFIG_CONSOLE_POLL |
265 | int (*poll_init)(struct tty_driver *driver, int line, char *options); | 263 | int (*poll_init)(struct tty_driver *driver, int line, char *options); |