diff options
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 130 |
1 files changed, 95 insertions, 35 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 8846d3b99845..c7763743a3d6 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -207,7 +207,7 @@ void tty_add_file(struct tty_struct *tty, struct file *file) spin_unlock(&tty->files_lock); } -/** +/* * tty_free_file - free file->private_data * * This shall be used only for fail path handling when tty_add_file was not @@ -517,8 +517,6 @@ static const struct file_operations hung_up_tty_fops = { static DEFINE_SPINLOCK(redirect_lock); static struct file *redirect; -extern void tty_sysctl_init(void); - /** * tty_wakeup - request more data * @tty: terminal @@ -546,8 +544,32 @@ void tty_wakeup(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_wakeup); /** + * tty_release_redirect - Release a redirect on a pty if present + * @tty: tty device + * + * This is available to the pty code so if the master closes, if the + * slave is a redirect it can release the redirect. It returns the + * filp for the redirect, which must be fput when the operations on + * the tty are completed. + */ +struct file *tty_release_redirect(struct tty_struct *tty) +{ + struct file *f = NULL; + + spin_lock(&redirect_lock); + if (redirect && file_tty(redirect) == tty) { + f = redirect; + redirect = NULL; + } + spin_unlock(&redirect_lock); + + return f; +} + +/** * __tty_hangup - actual handler for hangup events * @tty: tty device + * @exit_session: if non-zero, signal all foreground group processes * * This can be called by a "kworker" kernel thread. That is process * synchronous but doesn't hold any locks, so we need to make sure we @@ -570,7 +592,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); static void __tty_hangup(struct tty_struct *tty, int exit_session) { struct file *cons_filp = NULL; - struct file *filp, *f = NULL; + struct file *filp, *f; struct tty_file_private *priv; int closecount = 0, n; int refs; @@ -578,13 +600,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) if (!tty) return; - - spin_lock(&redirect_lock); - if (redirect && file_tty(redirect) == tty) { - f = redirect; - redirect = NULL; - } - spin_unlock(&redirect_lock); + f = tty_release_redirect(tty); tty_lock(tty); @@ -1129,7 +1145,7 @@ ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter) return tty_write(iocb, iter); } -/** +/* * tty_send_xchar - send priority character * * Send a high priority character to the tty even if stopped @@ -1207,6 +1223,7 @@ static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) /** * tty_driver_lookup_tty() - find an existing tty, if any * @driver: the driver for the tty + * @file: file object * @idx: the minor number * * Return the tty, if found. If not found, return NULL or ERR_PTR() if the @@ -1558,6 +1575,8 @@ EXPORT_SYMBOL(tty_kref_put); /** * release_tty - release tty structure memory + * @tty: tty device release + * @idx: index of the tty device release * * Release both @tty and a possible linked partner (think pty pair), * and decrement the refcount of the backing module. @@ -1935,22 +1954,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, return driver; } -/** - * tty_kopen - open a tty device for kernel - * @device: dev_t of device to open - * - * Opens tty exclusively for kernel. Performs the driver lookup, - * makes sure it's not already opened and performs the first-time - * tty initialization. - * - * Returns the locked initialized &tty_struct - * - * Claims the global tty_mutex to serialize: - * - concurrent first-time tty initialization - * - concurrent tty driver removal w/ lookup - * - concurrent tty removal from driver table - */ -struct tty_struct *tty_kopen(dev_t device) +static struct tty_struct *tty_kopen(dev_t device, int shared) { struct tty_struct *tty; struct tty_driver *driver; @@ -1965,7 +1969,7 @@ struct tty_struct *tty_kopen(dev_t device) /* check whether we're reopening an existing tty */ tty = tty_driver_lookup_tty(driver, NULL, index); - if (IS_ERR(tty)) + if (IS_ERR(tty) || shared) goto out; if (tty) { @@ -1983,7 +1987,42 @@ out: tty_driver_kref_put(driver); return tty; } -EXPORT_SYMBOL_GPL(tty_kopen); + +/** + * tty_kopen_exclusive - open a tty device for kernel + * @device: dev_t of device to open + * + * Opens tty exclusively for kernel. Performs the driver lookup, + * makes sure it's not already opened and performs the first-time + * tty initialization. + * + * Returns the locked initialized &tty_struct + * + * Claims the global tty_mutex to serialize: + * - concurrent first-time tty initialization + * - concurrent tty driver removal w/ lookup + * - concurrent tty removal from driver table + */ +struct tty_struct *tty_kopen_exclusive(dev_t device) +{ + return tty_kopen(device, 0); +} +EXPORT_SYMBOL_GPL(tty_kopen_exclusive); + +/** + * tty_kopen_shared - open a tty device for shared in-kernel use + * @device: dev_t of device to open + * + * Opens an already existing tty for in-kernel use. Compared to + * tty_kopen_exclusive() above it doesn't ensure to be the only user. + * + * Locking is identical to tty_kopen() above. + */ +struct tty_struct *tty_kopen_shared(dev_t device) +{ + return tty_kopen(device, 1); +} +EXPORT_SYMBOL_GPL(tty_kopen_shared); /** * tty_open_by_driver - open a tty device @@ -2528,15 +2567,36 @@ static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd, return tty->ops->tiocmset(tty, set, clear); } +/** + * tty_get_icount - get tty statistics + * @tty: tty device + * @icount: output parameter + * + * Gets a copy of the tty's icount statistics. + * + * Locking: none (up to the driver) + */ +int tty_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + memset(icount, 0, sizeof(*icount)); + + if (tty->ops->get_icount) + return tty->ops->get_icount(tty, icount); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(tty_get_icount); + static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) { - int retval = -EINVAL; struct serial_icounter_struct icount; - memset(&icount, 0, sizeof(icount)); - if (tty->ops->get_icount) - retval = tty->ops->get_icount(tty, &icount); + int retval; + + retval = tty_get_icount(tty, &icount); if (retval != 0) return retval; + if (copy_to_user(arg, &icount, sizeof(icount))) return -EFAULT; return 0; @@ -3032,7 +3092,7 @@ static struct device *tty_get_device(struct tty_struct *tty) } -/** +/* * alloc_tty_struct * * This subroutine allocates and initializes a tty structure. |