return 0;
}
+/**
+ * pty_common_install - set up the pty pair
+ * @driver: the pty driver
+ * @tty: the tty being instantiated
+ * @bool: legacy, true if this is BSD style
+ *
+ * Perform the initial set up for the tty/pty pair. Called from the
+ * tty layer when the port is first opened.
+ *
+ * Locking: the caller must hold the tty_mutex
+ */
static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
bool legacy)
{
return pty_common_install(driver, tty, true);
}
+static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct tty_struct *pair = tty->link;
+ driver->ttys[tty->index] = NULL;
+ if (pair)
+ pair->driver->ttys[pair->index] = NULL;
+}
+
static int pty_bsd_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
.cleanup = pty_cleanup,
- .resize = pty_resize
+ .resize = pty_resize,
+ .remove = pty_remove
};
static const struct tty_operations slave_pty_ops_bsd = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.cleanup = pty_cleanup,
- .resize = pty_resize
+ .resize = pty_resize,
+ .remove = pty_remove
};
static void __init legacy_pty_init(void)
* in use. It also gets called when setup of a device fails.
*
* Locking:
- * tty_mutex - sometimes only
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
*
* and decrement the refcount of the backing module.
*
* Locking:
- * tty_mutex - sometimes only
+ * tty_mutex
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
- * FIXME: should we require tty_mutex is held here ??
*
*/
static void release_tty(struct tty_struct *tty, int idx)
{
/* This should always be true but check for the moment */
WARN_ON(tty->index != idx);
-
+ WARN_ON(!mutex_is_locked(&tty_mutex));
if (tty->ops->shutdown)
tty->ops->shutdown(tty);
tty_free_termios(tty);
* The closing flags are now consistent with the open counts on
* both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing.
+ *
+ * We must *not* drop the tty_mutex until we ensure that a further
+ * entry into tty_open can not pick up this tty.
*/
if (pty_master) {
if (--o_tty->count < 0) {
}
mutex_unlock(&tty_mutex);
+ tty_unlock();
+ /* At this point the TTY_CLOSING flag should ensure a dead tty
+ cannot be re-opened by a racing opener */
/* check whether both sides are closing ... */
- if (!tty_closing || (o_tty && !o_tty_closing)) {
- tty_unlock();
+ if (!tty_closing || (o_tty && !o_tty_closing))
return 0;
- }
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__);
* The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure.
*/
+ mutex_lock(&tty_mutex);
release_tty(tty, idx);
+ mutex_unlock(&tty_mutex);
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
- tty_unlock();
+
return 0;
}
* race with the set_ldisc code path.
*/
- tty_unlock();
tty_ldisc_halt(tty);
tty_ldisc_flush_works(tty);
tty_lock();
tty_set_termios_ldisc(tty, N_TTY);
mutex_unlock(&tty->ldisc_mutex);
+ tty_unlock();
+
/* This will need doing differently if we need to lock */
if (o_tty)
tty_ldisc_release(o_tty, NULL);