[PATCH v2 10/10] tty: Refactor tty_open()

From: Peter Hurley
Date: Sun Jan 10 2016 - 00:15:50 EST


Extract the driver lookup and reopen-or-initialize logic into helper
function tty_open_by_driver(). No functional change.

Signed-off-by: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx>
---
drivers/tty/tty_io.c | 120 ++++++++++++++++++++++++++++-----------------------
1 file changed, 67 insertions(+), 53 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d223e54..cef913c 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2001,6 +2001,69 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
}

/**
+ * 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);
+ 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
* @filp: file pointer to tty
@@ -2028,8 +2091,6 @@ static int tty_open(struct inode *inode, struct file *filp)
{
struct tty_struct *tty;
int noctty, retval;
- struct tty_driver *driver = NULL;
- int index;
dev_t device = inode->i_rdev;
unsigned saved_flags = filp->f_flags;

@@ -2040,53 +2101,15 @@ retry_open:
if (retval)
return -ENOMEM;

- index = -1;
- retval = 0;
-
tty = tty_open_current_tty(device, filp);
- if (!tty) {
- mutex_lock(&tty_mutex);
- driver = tty_lookup_driver(device, filp, &index);
- if (IS_ERR(driver)) {
- retval = PTR_ERR(driver);
- goto err_unlock;
- }
-
- /* check whether we're reopening an existing tty */
- tty = tty_driver_lookup_tty(driver, inode, index);
- if (IS_ERR(tty)) {
- retval = PTR_ERR(tty);
- goto err_unlock;
- }
-
- if (tty) {
- mutex_unlock(&tty_mutex);
- retval = tty_lock_interruptible(tty);
- if (retval) {
- if (retval == -EINTR)
- retval = -ERESTARTSYS;
- goto err_unref;
- }
- /* 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);
- }
-
- tty_driver_kref_put(driver);
- }
+ if (!tty)
+ tty = tty_open_by_driver(device, inode, filp);

if (IS_ERR(tty)) {
+ tty_free_file(filp);
retval = PTR_ERR(tty);
if (retval != -EAGAIN || signal_pending(current))
- goto err_file;
- tty_free_file(filp);
+ return retval;
schedule();
goto retry_open;
}
@@ -2157,15 +2180,6 @@ retry_open:
read_unlock(&tasklist_lock);
tty_unlock(tty);
return 0;
-err_unlock:
- mutex_unlock(&tty_mutex);
-err_unref:
- /* after locks to avoid deadlock */
- if (!IS_ERR_OR_NULL(driver))
- tty_driver_kref_put(driver);
-err_file:
- tty_free_file(filp);
- return retval;
}


--
2.7.0