diff options
Diffstat (limited to 'drivers/char/tty_io.c')
| -rw-r--r-- | drivers/char/tty_io.c | 77 |
1 files changed, 43 insertions, 34 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0e6866fe0f96..daeb8f766971 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -2496,45 +2496,26 @@ 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 (not the same as 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 | ||
| 2515 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | 2509 | int 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))) | 2515 | /* For a PTY we need to lock the tty side */ |
| 2523 | return -EFAULT; | 2516 | mutex_lock(&real_tty->termios_mutex); |
| 2524 | 2517 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) | |
| 2525 | mutex_lock(&tty->termios_mutex); | ||
| 2526 | if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) | ||
| 2527 | goto done; | 2518 | 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 | 2519 | /* Get the PID values and reference them so we can |
| 2539 | avoid holding the tty ctrl lock while sending signals */ | 2520 | avoid holding the tty ctrl lock while sending signals */ |
| 2540 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2521 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
| @@ -2550,14 +2531,42 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | |||
| 2550 | put_pid(pgrp); | 2531 | put_pid(pgrp); |
| 2551 | put_pid(rpgrp); | 2532 | put_pid(rpgrp); |
| 2552 | 2533 | ||
| 2553 | tty->winsize = tmp_ws; | 2534 | tty->winsize = *ws; |
| 2554 | real_tty->winsize = tmp_ws; | 2535 | real_tty->winsize = *ws; |
| 2555 | done: | 2536 | done: |
| 2556 | mutex_unlock(&tty->termios_mutex); | 2537 | mutex_unlock(&real_tty->termios_mutex); |
| 2557 | return 0; | 2538 | return 0; |
| 2558 | } | 2539 | } |
| 2559 | 2540 | ||
| 2560 | /** | 2541 | /** |
| 2542 | * tiocswinsz - implement window size set ioctl | ||
| 2543 | * @tty; tty | ||
| 2544 | * @arg: user buffer for result | ||
| 2545 | * | ||
| 2546 | * Copies the user idea of the window size to the kernel. Traditionally | ||
| 2547 | * this is just advisory information but for the Linux console it | ||
| 2548 | * actually has driver level meaning and triggers a VC resize. | ||
| 2549 | * | ||
| 2550 | * Locking: | ||
| 2551 | * Driver dependant. The default do_resize method takes the | ||
| 2552 | * tty termios mutex and ctrl_lock. The console takes its own lock | ||
| 2553 | * then calls into the default method. | ||
| 2554 | */ | ||
| 2555 | |||
| 2556 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | ||
| 2557 | struct winsize __user *arg) | ||
| 2558 | { | ||
| 2559 | struct winsize tmp_ws; | ||
| 2560 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | ||
| 2561 | return -EFAULT; | ||
| 2562 | |||
| 2563 | if (tty->ops->resize) | ||
| 2564 | return tty->ops->resize(tty, real_tty, &tmp_ws); | ||
| 2565 | else | ||
| 2566 | return tty_do_resize(tty, real_tty, &tmp_ws); | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | /** | ||
| 2561 | * tioccons - allow admin to move logical console | 2570 | * tioccons - allow admin to move logical console |
| 2562 | * @file: the file to become console | 2571 | * @file: the file to become console |
| 2563 | * | 2572 | * |
