diff options
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 892c92354745..5cec01c75691 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1463,13 +1463,13 @@ static int tty_reopen(struct tty_struct *tty) | |||
1463 | { | 1463 | { |
1464 | struct tty_driver *driver = tty->driver; | 1464 | struct tty_driver *driver = tty->driver; |
1465 | 1465 | ||
1466 | if (!tty->count) | ||
1467 | return -EIO; | ||
1468 | |||
1469 | if (driver->type == TTY_DRIVER_TYPE_PTY && | 1466 | if (driver->type == TTY_DRIVER_TYPE_PTY && |
1470 | driver->subtype == PTY_TYPE_MASTER) | 1467 | driver->subtype == PTY_TYPE_MASTER) |
1471 | return -EIO; | 1468 | return -EIO; |
1472 | 1469 | ||
1470 | if (!tty->count) | ||
1471 | return -EAGAIN; | ||
1472 | |||
1473 | if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) | 1473 | if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) |
1474 | return -EBUSY; | 1474 | return -EBUSY; |
1475 | 1475 | ||
@@ -2065,7 +2065,12 @@ retry_open: | |||
2065 | 2065 | ||
2066 | if (tty) { | 2066 | if (tty) { |
2067 | mutex_unlock(&tty_mutex); | 2067 | mutex_unlock(&tty_mutex); |
2068 | tty_lock(tty); | 2068 | retval = tty_lock_interruptible(tty); |
2069 | if (retval) { | ||
2070 | if (retval == -EINTR) | ||
2071 | retval = -ERESTARTSYS; | ||
2072 | goto err_unref; | ||
2073 | } | ||
2069 | /* safe to drop the kref from tty_driver_lookup_tty() */ | 2074 | /* safe to drop the kref from tty_driver_lookup_tty() */ |
2070 | tty_kref_put(tty); | 2075 | tty_kref_put(tty); |
2071 | retval = tty_reopen(tty); | 2076 | retval = tty_reopen(tty); |
@@ -2083,7 +2088,11 @@ retry_open: | |||
2083 | 2088 | ||
2084 | if (IS_ERR(tty)) { | 2089 | if (IS_ERR(tty)) { |
2085 | retval = PTR_ERR(tty); | 2090 | retval = PTR_ERR(tty); |
2086 | goto err_file; | 2091 | if (retval != -EAGAIN || signal_pending(current)) |
2092 | goto err_file; | ||
2093 | tty_free_file(filp); | ||
2094 | schedule(); | ||
2095 | goto retry_open; | ||
2087 | } | 2096 | } |
2088 | 2097 | ||
2089 | tty_add_file(tty, filp); | 2098 | tty_add_file(tty, filp); |
@@ -2152,6 +2161,7 @@ retry_open: | |||
2152 | return 0; | 2161 | return 0; |
2153 | err_unlock: | 2162 | err_unlock: |
2154 | mutex_unlock(&tty_mutex); | 2163 | mutex_unlock(&tty_mutex); |
2164 | err_unref: | ||
2155 | /* after locks to avoid deadlock */ | 2165 | /* after locks to avoid deadlock */ |
2156 | if (!IS_ERR_OR_NULL(driver)) | 2166 | if (!IS_ERR_OR_NULL(driver)) |
2157 | tty_driver_kref_put(driver); | 2167 | tty_driver_kref_put(driver); |
@@ -2649,6 +2659,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
2649 | } | 2659 | } |
2650 | 2660 | ||
2651 | /** | 2661 | /** |
2662 | * tiocgetd - get line discipline | ||
2663 | * @tty: tty device | ||
2664 | * @p: pointer to user data | ||
2665 | * | ||
2666 | * Retrieves the line discipline id directly from the ldisc. | ||
2667 | * | ||
2668 | * Locking: waits for ldisc reference (in case the line discipline | ||
2669 | * is changing or the tty is being hungup) | ||
2670 | */ | ||
2671 | |||
2672 | static int tiocgetd(struct tty_struct *tty, int __user *p) | ||
2673 | { | ||
2674 | struct tty_ldisc *ld; | ||
2675 | int ret; | ||
2676 | |||
2677 | ld = tty_ldisc_ref_wait(tty); | ||
2678 | ret = put_user(ld->ops->num, p); | ||
2679 | tty_ldisc_deref(ld); | ||
2680 | return ret; | ||
2681 | } | ||
2682 | |||
2683 | /** | ||
2652 | * send_break - performed time break | 2684 | * send_break - performed time break |
2653 | * @tty: device to break on | 2685 | * @tty: device to break on |
2654 | * @duration: timeout in mS | 2686 | * @duration: timeout in mS |
@@ -2874,7 +2906,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2874 | case TIOCGSID: | 2906 | case TIOCGSID: |
2875 | return tiocgsid(tty, real_tty, p); | 2907 | return tiocgsid(tty, real_tty, p); |
2876 | case TIOCGETD: | 2908 | case TIOCGETD: |
2877 | return put_user(tty->ldisc->ops->num, (int __user *)p); | 2909 | return tiocgetd(tty, p); |
2878 | case TIOCSETD: | 2910 | case TIOCSETD: |
2879 | return tiocsetd(tty, p); | 2911 | return tiocsetd(tty, p); |
2880 | case TIOCVHANGUP: | 2912 | case TIOCVHANGUP: |