Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6203d0c authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman
Browse files

tty: Refactor tty_open()



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

Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 11e1d4aa
Loading
Loading
Loading
Loading
+67 −53
Original line number Original line Diff line number Diff line
@@ -1995,62 +1995,41 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
}
}


/**
/**
 *	tty_open		-	open a tty device
 *	tty_open_by_driver	-	open a tty device
 *	@device: dev_t of device to open
 *	@inode: inode of device file
 *	@inode: inode of device file
 *	@filp: file pointer to tty
 *	@filp: file pointer to tty
 *
 *
 *	tty_open and tty_release keep up the tty count that contains the
 *	Performs the driver lookup, checks for a reopen, or otherwise
 *	number of opens done on a tty. We cannot use the inode-count, as
 *	performs the first-time tty initialization.
 *	different inodes might point to the same tty.
 *
 *	Open-counting is needed for pty masters, as well as for keeping
 *	track of serial lines: DTR is dropped when the last close happens.
 *	(This is not done solely through tty->count, now.  - Ted 1/27/92)
 *
 *
 *	The termios state of a pty is reset on first open so that
 *	Returns the locked initialized or re-opened &tty_struct
 *	settings don't persist across reuse.
 *
 *
 *	Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
 *	Claims the global tty_mutex to serialize:
 *		 tty->count should protect the rest.
 *	  - concurrent first-time tty initialization
 *		 ->siglock protects ->signal/->sighand
 *	  - concurrent tty driver removal w/ lookup
 *
 *	  - concurrent tty removal from driver table
 *	Note: the tty_unlock/lock cases without a ref are only safe due to
 *	tty_mutex
 */
 */

static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
static int tty_open(struct inode *inode, struct file *filp)
					     struct file *filp)
{
{
	struct tty_struct *tty;
	struct tty_struct *tty;
	int noctty, retval;
	struct tty_driver *driver = NULL;
	struct tty_driver *driver = NULL;
	int index;
	int index = -1;
	dev_t device = inode->i_rdev;
	int retval;
	unsigned saved_flags = filp->f_flags;

	nonseekable_open(inode, filp);

retry_open:
	retval = tty_alloc_file(filp);
	if (retval)
		return -ENOMEM;

	index  = -1;
	retval = 0;


	tty = tty_open_current_tty(device, filp);
	if (!tty) {
	mutex_lock(&tty_mutex);
	mutex_lock(&tty_mutex);
	driver = tty_lookup_driver(device, filp, &index);
	driver = tty_lookup_driver(device, filp, &index);
	if (IS_ERR(driver)) {
	if (IS_ERR(driver)) {
			retval = PTR_ERR(driver);
		mutex_unlock(&tty_mutex);
			goto err_unlock;
		return ERR_CAST(driver);
	}
	}


	/* check whether we're reopening an existing tty */
	/* check whether we're reopening an existing tty */
	tty = tty_driver_lookup_tty(driver, inode, index);
	tty = tty_driver_lookup_tty(driver, inode, index);
	if (IS_ERR(tty)) {
	if (IS_ERR(tty)) {
			retval = PTR_ERR(tty);
		mutex_unlock(&tty_mutex);
			goto err_unlock;
		goto out;
	}
	}


	if (tty) {
	if (tty) {
@@ -2059,7 +2038,8 @@ static int tty_open(struct inode *inode, struct file *filp)
		if (retval) {
		if (retval) {
			if (retval == -EINTR)
			if (retval == -EINTR)
				retval = -ERESTARTSYS;
				retval = -ERESTARTSYS;
				goto err_unref;
			tty = ERR_PTR(retval);
			goto out;
		}
		}
		/* safe to drop the kref from tty_driver_lookup_tty() */
		/* safe to drop the kref from tty_driver_lookup_tty() */
		tty_kref_put(tty);
		tty_kref_put(tty);
@@ -2072,15 +2052,58 @@ static int tty_open(struct inode *inode, struct file *filp)
		tty = tty_init_dev(driver, index);
		tty = tty_init_dev(driver, index);
		mutex_unlock(&tty_mutex);
		mutex_unlock(&tty_mutex);
	}
	}

out:
	tty_driver_kref_put(driver);
	tty_driver_kref_put(driver);
	return tty;
}
}


/**
 *	tty_open		-	open a tty device
 *	@inode: inode of device file
 *	@filp: file pointer to tty
 *
 *	tty_open and tty_release keep up the tty count that contains the
 *	number of opens done on a tty. We cannot use the inode-count, as
 *	different inodes might point to the same tty.
 *
 *	Open-counting is needed for pty masters, as well as for keeping
 *	track of serial lines: DTR is dropped when the last close happens.
 *	(This is not done solely through tty->count, now.  - Ted 1/27/92)
 *
 *	The termios state of a pty is reset on first open so that
 *	settings don't persist across reuse.
 *
 *	Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
 *		 tty->count should protect the rest.
 *		 ->siglock protects ->signal/->sighand
 *
 *	Note: the tty_unlock/lock cases without a ref are only safe due to
 *	tty_mutex
 */

static int tty_open(struct inode *inode, struct file *filp)
{
	struct tty_struct *tty;
	int noctty, retval;
	dev_t device = inode->i_rdev;
	unsigned saved_flags = filp->f_flags;

	nonseekable_open(inode, filp);

retry_open:
	retval = tty_alloc_file(filp);
	if (retval)
		return -ENOMEM;

	tty = tty_open_current_tty(device, filp);
	if (!tty)
		tty = tty_open_by_driver(device, inode, filp);

	if (IS_ERR(tty)) {
	if (IS_ERR(tty)) {
		tty_free_file(filp);
		retval = PTR_ERR(tty);
		retval = PTR_ERR(tty);
		if (retval != -EAGAIN || signal_pending(current))
		if (retval != -EAGAIN || signal_pending(current))
			goto err_file;
			return retval;
		tty_free_file(filp);
		schedule();
		schedule();
		goto retry_open;
		goto retry_open;
	}
	}
@@ -2151,15 +2174,6 @@ static int tty_open(struct inode *inode, struct file *filp)
	read_unlock(&tasklist_lock);
	read_unlock(&tasklist_lock);
	tty_unlock(tty);
	tty_unlock(tty);
	return 0;
	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;
}
}