aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_io.c72
-rw-r--r--drivers/char/vt.c82
-rw-r--r--drivers/char/vt_ioctl.c4
-rw-r--r--include/linux/tty.h2
-rw-r--r--include/linux/tty_driver.h14
-rw-r--r--include/linux/vt_kern.h1
6 files changed, 121 insertions, 54 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 0e6866fe0f96..a27160ba21d7 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2496,45 +2496,25 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
2496} 2496}
2497 2497
2498/** 2498/**
2499 * tiocswinsz - implement window size set ioctl 2499 * tty_do_resize - resize event
2500 * @tty; tty 2500 * @tty: tty being resized
2501 * @arg: user buffer for result 2501 * @real_tty: real tty (if using a pty/tty pair)
2502 * @rows: rows (character)
2503 * @cols: cols (character)
2502 * 2504 *
2503 * Copies the user idea of the window size to the kernel. Traditionally 2505 * Update the termios variables and send the neccessary signals to
2504 * this is just advisory information but for the Linux console it 2506 * peform a terminal resize correctly
2505 * actually has driver level meaning and triggers a VC resize.
2506 *
2507 * Locking:
2508 * Called function use the console_sem is used to ensure we do
2509 * not try and resize the console twice at once.
2510 * The tty->termios_mutex is used to ensure we don't double
2511 * resize and get confused. Lock order - tty->termios_mutex before
2512 * console sem
2513 */ 2507 */
2514 2508
2515static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, 2509int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
2516 struct winsize __user *arg) 2510 struct winsize *ws)
2517{ 2511{
2518 struct winsize tmp_ws;
2519 struct pid *pgrp, *rpgrp; 2512 struct pid *pgrp, *rpgrp;
2520 unsigned long flags; 2513 unsigned long flags;
2521 2514
2522 if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
2523 return -EFAULT;
2524
2525 mutex_lock(&tty->termios_mutex); 2515 mutex_lock(&tty->termios_mutex);
2526 if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) 2516 if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
2527 goto done; 2517 goto done;
2528
2529#ifdef CONFIG_VT
2530 if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
2531 if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
2532 tmp_ws.ws_row)) {
2533 mutex_unlock(&tty->termios_mutex);
2534 return -ENXIO;
2535 }
2536 }
2537#endif
2538 /* Get the PID values and reference them so we can 2518 /* Get the PID values and reference them so we can
2539 avoid holding the tty ctrl lock while sending signals */ 2519 avoid holding the tty ctrl lock while sending signals */
2540 spin_lock_irqsave(&tty->ctrl_lock, flags); 2520 spin_lock_irqsave(&tty->ctrl_lock, flags);
@@ -2550,14 +2530,42 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
2550 put_pid(pgrp); 2530 put_pid(pgrp);
2551 put_pid(rpgrp); 2531 put_pid(rpgrp);
2552 2532
2553 tty->winsize = tmp_ws; 2533 tty->winsize = *ws;
2554 real_tty->winsize = tmp_ws; 2534 real_tty->winsize = *ws;
2555done: 2535done:
2556 mutex_unlock(&tty->termios_mutex); 2536 mutex_unlock(&tty->termios_mutex);
2557 return 0; 2537 return 0;
2558} 2538}
2559 2539
2560/** 2540/**
2541 * tiocswinsz - implement window size set ioctl
2542 * @tty; tty
2543 * @arg: user buffer for result
2544 *
2545 * Copies the user idea of the window size to the kernel. Traditionally
2546 * this is just advisory information but for the Linux console it
2547 * actually has driver level meaning and triggers a VC resize.
2548 *
2549 * Locking:
2550 * Driver dependant. The default do_resize method takes the
2551 * tty termios mutex and ctrl_lock. The console takes its own lock
2552 * then calls into the default method.
2553 */
2554
2555static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
2556 struct winsize __user *arg)
2557{
2558 struct winsize tmp_ws;
2559 if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
2560 return -EFAULT;
2561
2562 if (tty->ops->resize)
2563 return tty->ops->resize(tty, real_tty, &tmp_ws);
2564 else
2565 return tty_do_resize(tty, real_tty, &tmp_ws);
2566}
2567
2568/**
2561 * tioccons - allow admin to move logical console 2569 * tioccons - allow admin to move logical console
2562 * @file: the file to become console 2570 * @file: the file to become console
2563 * 2571 *
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1bc00c9d860d..60359c360912 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -803,7 +803,25 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
803 */ 803 */
804#define VC_RESIZE_MAXCOL (32767) 804#define VC_RESIZE_MAXCOL (32767)
805#define VC_RESIZE_MAXROW (32767) 805#define VC_RESIZE_MAXROW (32767)
806int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) 806
807/**
808 * vc_do_resize - resizing method for the tty
809 * @tty: tty being resized
810 * @real_tty: real tty (different to tty if a pty/tty pair)
811 * @vc: virtual console private data
812 * @cols: columns
813 * @lines: lines
814 *
815 * Resize a virtual console, clipping according to the actual constraints.
816 * If the caller passes a tty structure then update the termios winsize
817 * information and perform any neccessary signal handling.
818 *
819 * Caller must hold the console semaphore. Takes the termios mutex and
820 * ctrl_lock of the tty IFF a tty is passed.
821 */
822
823static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
824 struct vc_data *vc, unsigned int cols, unsigned int lines)
807{ 825{
808 unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; 826 unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
809 unsigned int old_cols, old_rows, old_row_size, old_screen_size; 827 unsigned int old_cols, old_rows, old_row_size, old_screen_size;
@@ -907,24 +925,15 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
907 gotoxy(vc, vc->vc_x, vc->vc_y); 925 gotoxy(vc, vc->vc_x, vc->vc_y);
908 save_cur(vc); 926 save_cur(vc);
909 927
910 if (vc->vc_tty) { 928 if (tty) {
911 struct winsize ws, *cws = &vc->vc_tty->winsize; 929 /* Rewrite the requested winsize data with the actual
912 struct pid *pgrp = NULL; 930 resulting sizes */
913 931 struct winsize ws;
914 memset(&ws, 0, sizeof(ws)); 932 memset(&ws, 0, sizeof(ws));
915 ws.ws_row = vc->vc_rows; 933 ws.ws_row = vc->vc_rows;
916 ws.ws_col = vc->vc_cols; 934 ws.ws_col = vc->vc_cols;
917 ws.ws_ypixel = vc->vc_scan_lines; 935 ws.ws_ypixel = vc->vc_scan_lines;
918 936 tty_do_resize(tty, real_tty, &ws);
919 spin_lock_irq(&vc->vc_tty->ctrl_lock);
920 if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col))
921 pgrp = get_pid(vc->vc_tty->pgrp);
922 spin_unlock_irq(&vc->vc_tty->ctrl_lock);
923 if (pgrp) {
924 kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
925 put_pid(pgrp);
926 }
927 *cws = ws;
928 } 937 }
929 938
930 if (CON_IS_VISIBLE(vc)) 939 if (CON_IS_VISIBLE(vc))
@@ -932,14 +941,47 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
932 return err; 941 return err;
933} 942}
934 943
935int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) 944/**
945 * vc_resize - resize a VT
946 * @vc: virtual console
947 * @cols: columns
948 * @rows: rows
949 *
950 * Resize a virtual console as seen from the console end of things. We
951 * use the common vc_do_resize methods to update the structures. The
952 * caller must hold the console sem to protect console internals and
953 * vc->vc_tty
954 */
955
956int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
957{
958 return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows);
959}
960
961/**
962 * vt_resize - resize a VT
963 * @tty: tty to resize
964 * @real_tty: tty if a pty/tty pair
965 * @ws: winsize attributes
966 *
967 * Resize a virtual terminal. This is called by the tty layer as we
968 * register our own handler for resizing. The mutual helper does all
969 * the actual work.
970 *
971 * Takes the console sem and the called methods then take the tty
972 * termios_mutex and the tty ctrl_lock in that order.
973 */
974
975int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty,
976 struct winsize *ws)
936{ 977{
937 int rc; 978 struct vc_data *vc = tty->driver_data;
979 int ret;
938 980
939 acquire_console_sem(); 981 acquire_console_sem();
940 rc = vc_resize(vc, cols, lines); 982 ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row);
941 release_console_sem(); 983 release_console_sem();
942 return rc; 984 return ret;
943} 985}
944 986
945void vc_deallocate(unsigned int currcons) 987void vc_deallocate(unsigned int currcons)
@@ -2907,6 +2949,7 @@ static const struct tty_operations con_ops = {
2907 .start = con_start, 2949 .start = con_start,
2908 .throttle = con_throttle, 2950 .throttle = con_throttle,
2909 .unthrottle = con_unthrottle, 2951 .unthrottle = con_unthrottle,
2952 .resize = vt_resize,
2910}; 2953};
2911 2954
2912int __init vty_init(void) 2955int __init vty_init(void)
@@ -4061,7 +4104,6 @@ EXPORT_SYMBOL(default_blu);
4061EXPORT_SYMBOL(update_region); 4104EXPORT_SYMBOL(update_region);
4062EXPORT_SYMBOL(redraw_screen); 4105EXPORT_SYMBOL(redraw_screen);
4063EXPORT_SYMBOL(vc_resize); 4106EXPORT_SYMBOL(vc_resize);
4064EXPORT_SYMBOL(vc_lock_resize);
4065EXPORT_SYMBOL(fg_console); 4107EXPORT_SYMBOL(fg_console);
4066EXPORT_SYMBOL(console_blank_hook); 4108EXPORT_SYMBOL(console_blank_hook);
4067EXPORT_SYMBOL(console_blanked); 4109EXPORT_SYMBOL(console_blanked);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 3211afd9d57e..c904e9ad4a71 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -947,14 +947,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
947 get_user(cc, &vtsizes->v_cols)) 947 get_user(cc, &vtsizes->v_cols))
948 ret = -EFAULT; 948 ret = -EFAULT;
949 else { 949 else {
950 acquire_console_sem();
950 for (i = 0; i < MAX_NR_CONSOLES; i++) { 951 for (i = 0; i < MAX_NR_CONSOLES; i++) {
951 vc = vc_cons[i].d; 952 vc = vc_cons[i].d;
952 953
953 if (vc) { 954 if (vc) {
954 vc->vc_resize_user = 1; 955 vc->vc_resize_user = 1;
955 vc_lock_resize(vc_cons[i].d, cc, ll); 956 vc_resize(vc_cons[i].d, cc, ll);
956 } 957 }
957 } 958 }
959 release_console_sem();
958 } 960 }
959 break; 961 break;
960 } 962 }
diff --git a/include/linux/tty.h b/include/linux/tty.h
index e3579cb086e0..0cbec74ec086 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -331,6 +331,8 @@ extern int tty_write_room(struct tty_struct *tty);
331extern void tty_driver_flush_buffer(struct tty_struct *tty); 331extern void tty_driver_flush_buffer(struct tty_struct *tty);
332extern void tty_throttle(struct tty_struct *tty); 332extern void tty_throttle(struct tty_struct *tty);
333extern void tty_unthrottle(struct tty_struct *tty); 333extern void tty_unthrottle(struct tty_struct *tty);
334extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
335 struct winsize *ws);
334 336
335extern int is_current_pgrp_orphaned(void); 337extern int is_current_pgrp_orphaned(void);
336extern struct pid *tty_get_pgrp(struct tty_struct *tty); 338extern struct pid *tty_get_pgrp(struct tty_struct *tty);
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index e1065ac0d922..16d27944c321 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -168,6 +168,18 @@
168 * 168 *
169 * Optional: If not provided then the write method is called under 169 * Optional: If not provided then the write method is called under
170 * the atomic write lock to keep it serialized with the ldisc. 170 * the atomic write lock to keep it serialized with the ldisc.
171 *
172 * int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty,
173 * unsigned int rows, unsigned int cols);
174 *
175 * Called when a termios request is issued which changes the
176 * requested terminal geometry.
177 *
178 * Optional: the default action is to update the termios structure
179 * without error. This is usually the correct behaviour. Drivers should
180 * not force errors here if they are not resizable objects (eg a serial
181 * line). See tty_do_resize() if you need to wrap the standard method
182 * in your own logic - the usual case.
171 */ 183 */
172 184
173#include <linux/fs.h> 185#include <linux/fs.h>
@@ -206,6 +218,8 @@ struct tty_operations {
206 int (*tiocmget)(struct tty_struct *tty, struct file *file); 218 int (*tiocmget)(struct tty_struct *tty, struct file *file);
207 int (*tiocmset)(struct tty_struct *tty, struct file *file, 219 int (*tiocmset)(struct tty_struct *tty, struct file *file,
208 unsigned int set, unsigned int clear); 220 unsigned int set, unsigned int clear);
221 int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty,
222 struct winsize *ws);
209#ifdef CONFIG_CONSOLE_POLL 223#ifdef CONFIG_CONSOLE_POLL
210 int (*poll_init)(struct tty_driver *driver, int line, char *options); 224 int (*poll_init)(struct tty_driver *driver, int line, char *options);
211 int (*poll_get_char)(struct tty_driver *driver, int line); 225 int (*poll_get_char)(struct tty_driver *driver, int line);
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 1c78d56c57e5..1cbd0a7db4e6 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -35,7 +35,6 @@ extern int fg_console, last_console, want_console;
35int vc_allocate(unsigned int console); 35int vc_allocate(unsigned int console);
36int vc_cons_allocated(unsigned int console); 36int vc_cons_allocated(unsigned int console);
37int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); 37int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
38int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
39void vc_deallocate(unsigned int console); 38void vc_deallocate(unsigned int console);
40void reset_palette(struct vc_data *vc); 39void reset_palette(struct vc_data *vc);
41void do_blank_screen(int entering_gfx); 40void do_blank_screen(int entering_gfx);