From: Stephen Rothwell Date: Thu, 11 Feb 2016 02:43:47 +0000 (+1100) Subject: Merge remote-tracking branch 'tty/tty-next' X-Git-Tag: next-20160211~19 X-Git-Url: https://git.karo-electronics.de/?p=karo-tx-linux.git;a=commitdiff_plain;h=2292705bd6c27b3ed2f83db8d2268d8006c027d7 Merge remote-tracking branch 'tty/tty-next' --- 2292705bd6c27b3ed2f83db8d2268d8006c027d7 diff --cc drivers/tty/pty.c index 2348fa613707,78170e7aa3a3..e16a49b507ef --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@@ -674,21 -660,10 +660,17 @@@ static int pty_unix98_install(struct tt return pty_common_install(driver, tty, false); } - static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) - { - } - /* this is called once with whichever end is closed last */ - static void pty_unix98_shutdown(struct tty_struct *tty) + static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { - devpts_kill_index(tty->driver_data, tty->index); + struct inode *ptmx_inode; + + if (tty->driver->subtype == PTY_TYPE_MASTER) + ptmx_inode = tty->driver_data; + else + ptmx_inode = tty->link->driver_data; + devpts_kill_index(ptmx_inode, tty->index); + devpts_del_ref(ptmx_inode); } static const struct tty_operations ptm_unix98_ops = { diff --cc drivers/tty/tty_io.c index a7eacef1bd22,8d26ed79bb4c..c14c45fefa70 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@@ -2003,6 -2008,69 +2008,68 @@@ static struct tty_driver *tty_lookup_dr return driver; } + /** + * tty_open_by_driver - open a tty device + * @device: dev_t of device to open + * @inode: inode of device file + * @filp: file pointer to tty + * + * Performs the driver lookup, checks for a reopen, or otherwise + * performs the first-time tty initialization. + * + * Returns the locked initialized or re-opened &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 + */ + static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode, + struct file *filp) + { + struct tty_struct *tty; + struct tty_driver *driver = NULL; + int index = -1; + int retval; + + mutex_lock(&tty_mutex); + driver = tty_lookup_driver(device, filp, &index); + if (IS_ERR(driver)) { + mutex_unlock(&tty_mutex); + return ERR_CAST(driver); + } + + /* check whether we're reopening an existing tty */ + tty = tty_driver_lookup_tty(driver, inode, index); + if (IS_ERR(tty)) { + mutex_unlock(&tty_mutex); + goto out; + } + + if (tty) { + mutex_unlock(&tty_mutex); + retval = tty_lock_interruptible(tty); ++ tty_kref_put(tty); /* drop kref from tty_driver_lookup_tty() */ + if (retval) { + if (retval == -EINTR) + retval = -ERESTARTSYS; + tty = ERR_PTR(retval); + goto out; + } - /* safe to drop the kref from tty_driver_lookup_tty() */ - tty_kref_put(tty); + retval = tty_reopen(tty); + if (retval < 0) { + tty_unlock(tty); + tty = ERR_PTR(retval); + } + } else { /* Returns with the tty_lock held for now */ + tty = tty_init_dev(driver, index); + mutex_unlock(&tty_mutex); + } + out: + tty_driver_kref_put(driver); + return tty; + } + /** * tty_open - open a tty device * @inode: inode of device file diff --cc drivers/tty/tty_mutex.c index dfa9ec03fa8e,75351e4b77df..d8bae67a6174 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@@ -26,13 -24,10 +26,13 @@@ int tty_lock_interruptible(struct tty_s if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) return -EIO; tty_kref_get(tty); - return mutex_lock_interruptible(&tty->legacy_mutex); + ret = mutex_lock_interruptible(&tty->legacy_mutex); + if (ret) + tty_kref_put(tty); + return ret; } - void __lockfunc tty_unlock(struct tty_struct *tty) + void tty_unlock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty)) return;