aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r--drivers/tty/tty_io.c44
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;
2153err_unlock: 2162err_unlock:
2154 mutex_unlock(&tty_mutex); 2163 mutex_unlock(&tty_mutex);
2164err_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
2672static 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: