aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 08:43:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:36 -0500
commitfc6f6238226e6d1248e1967eae2bf556eaf3ac17 (patch)
tree07cef0fafd30bd622dac1db4751e10734773c863
parenta47d545f5782cbde871b50bdf4a83379ed2da222 (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.c2
-rw-r--r--drivers/char/pty.c54
-rw-r--r--drivers/char/tty_io.c31
-rw-r--r--drivers/char/vt.c14
-rw-r--r--include/linux/tty.h3
-rw-r--r--include/linux/tty_driver.h6
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
244int 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 */
277done:
278 mutex_unlock(&tty->termios_mutex);
279 return 0;
280}
281
233static int pty_install(struct tty_driver *driver, struct tty_struct *tty) 282static 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
324static void __init legacy_pty_init(void) 375static 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
567static const struct tty_operations pty_unix98_ops = { 619static 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
2059int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, 2058int 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;
2086done: 2078done:
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
2106static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, 2098static 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
822static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, 822static 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
955int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) 955int 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
974int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty, 973int 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);
360extern void tty_driver_flush_buffer(struct tty_struct *tty); 360extern void tty_driver_flush_buffer(struct tty_struct *tty);
361extern void tty_throttle(struct tty_struct *tty); 361extern void tty_throttle(struct tty_struct *tty);
362extern void tty_unthrottle(struct tty_struct *tty); 362extern void tty_unthrottle(struct tty_struct *tty);
363extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, 363extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
364 struct winsize *ws);
365extern void tty_shutdown(struct tty_struct *tty); 364extern void tty_shutdown(struct tty_struct *tty);
366extern void tty_free_termios(struct tty_struct *tty); 365extern void tty_free_termios(struct tty_struct *tty);
367extern int is_current_pgrp_orphaned(void); 366extern 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);