EXPORT_SYMBOL(tty_vhangup);
+/**
+ * tty_vhangup_self - process vhangup for own ctty
+ *
+ * Perform a vhangup on the current controlling tty
+ */
+
+void tty_vhangup_self(void)
+{
+ struct tty_struct *tty;
+
+ tty = get_current_tty();
+ if (tty) {
+ tty_vhangup(tty);
+ tty_kref_put(tty);
+ }
+}
+
/**
* tty_hung_up_p - was tty hung up
* @filp: file pointer of tty
struct pid *tty_pgrp = NULL;
- mutex_lock(&tty_mutex);
tty = get_current_tty();
if (tty) {
tty_pgrp = get_pid(tty->pgrp);
- mutex_unlock(&tty_mutex);
lock_kernel();
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
kill_pgrp(old_pgrp, SIGCONT, on_exit);
put_pid(old_pgrp);
}
- mutex_unlock(&tty_mutex);
return;
}
if (tty_pgrp) {
current->signal->tty_old_pgrp = NULL;
spin_unlock_irq(¤t->sighand->siglock);
- mutex_lock(&tty_mutex);
tty = get_current_tty();
if (tty) {
unsigned long flags;
" = NULL", tty);
#endif
}
- mutex_unlock(&tty_mutex);
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
* init_dev - initialise a tty device
* @driver: tty driver we are opening a device on
* @idx: device index
- * @tty: returned tty structure
+ * @ret_tty: returned tty structure
+ * @first_ok: ok to open a new device (used by ptmx)
*
* Prepare a tty device. This may not be a "new" clean device but
* could also be an active device. The pty drivers require special
*/
static int init_dev(struct tty_driver *driver, int idx,
- struct tty_struct **ret_tty)
+ struct tty_struct **ret_tty, int first_ok)
{
struct tty_struct *tty, *o_tty;
struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
}
if (tty) goto fast_track;
+ if (driver->subtype == PTY_TYPE_MASTER &&
+ (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
+ retval = -EIO;
+ goto end_init;
+ }
/*
* First time open is complex, especially for PTY devices.
* This code guarantees that either everything succeeds and the
if (retval)
goto release_mem_out;
- goto success;
+ goto success;
/*
* This fast open can be used if the tty is already open.
goto end_init;
}
+void tty_free_termios(struct tty_struct *tty)
+{
+ struct ktermios *tp;
+ int idx = tty->index;
+ /* Kill this flag and push into drivers for locking etc */
+ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
+ /* FIXME: Locking on ->termios array */
+ tp = tty->termios;
+ tty->driver->termios[idx] = NULL;
+ kfree(tp);
+
+ tp = tty->termios_locked;
+ tty->driver->termios_locked[idx] = NULL;
+ kfree(tp);
+ }
+}
+EXPORT_SYMBOL(tty_free_termios);
+
+void tty_shutdown(struct tty_struct *tty)
+{
+ tty->driver->ttys[tty->index] = NULL;
+ tty_free_termios(tty);
+}
+EXPORT_SYMBOL(tty_shutdown);
+
/**
* release_one_tty - release tty structure memory
* @kref: kref of tty we are obliterating
{
struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
struct tty_driver *driver = tty->driver;
- int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
- struct ktermios *tp;
- int idx = tty->index;
-
- if (!devpts)
- tty->driver->ttys[idx] = NULL;
-
- if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- /* FIXME: Locking on ->termios array */
- tp = tty->termios;
- if (!devpts)
- tty->driver->termios[idx] = NULL;
- kfree(tp);
-
- tp = tty->termios_locked;
- if (!devpts)
- tty->driver->termios_locked[idx] = NULL;
- kfree(tp);
- }
-
+ if (tty->ops->shutdown)
+ tty->ops->shutdown(tty);
+ else
+ tty_shutdown(tty);
tty->magic = 0;
/* FIXME: locking on tty->driver->refcount */
tty->driver->refcount--;
}
/**
- * tty_open - open a tty device
+ * __tty_open - open a tty device
* @inode: inode of device file
* @filp: file pointer to tty
*
return -ENODEV;
}
got_driver:
- retval = init_dev(driver, index, &tty);
+ retval = init_dev(driver, index, &tty, 0);
mutex_unlock(&tty_mutex);
if (retval)
return retval;
return index;
mutex_lock(&tty_mutex);
- retval = init_dev(ptm_driver, index, &tty);
+ retval = init_dev(ptm_driver, index, &tty, 1);
mutex_unlock(&tty_mutex);
if (retval)
struct tty_struct *get_current_tty(void)
{
struct tty_struct *tty;
- WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
+ unsigned long flags;
+
+ spin_lock_irqsave(¤t->sighand->siglock, flags);
tty = tty_kref_get(current->signal->tty);
- /*
- * session->tty can be changed/cleared from under us, make sure we
- * issue the load. The obtained pointer, when not NULL, is valid as
- * long as we hold tty_mutex.
- */
- barrier();
+ spin_unlock_irqrestore(¤t->sighand->siglock, flags);
return tty;
}
EXPORT_SYMBOL_GPL(get_current_tty);