]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/tty_io.c
tty: shutdown method
[linux-2.6-omap-h63xx.git] / drivers / char / tty_io.c
index 913b50258f903f74367f475cb69f1747492c0bfc..f91704d57a4e3c288d70826c0bd717e523db86f3 100644 (file)
@@ -729,6 +729,23 @@ void tty_vhangup(struct tty_struct *tty)
 
 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
@@ -782,11 +799,9 @@ void disassociate_ctty(int on_exit)
        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);
@@ -803,7 +818,6 @@ void disassociate_ctty(int on_exit)
                        kill_pgrp(old_pgrp, SIGCONT, on_exit);
                        put_pid(old_pgrp);
                }
-               mutex_unlock(&tty_mutex);
                return;
        }
        if (tty_pgrp) {
@@ -818,7 +832,6 @@ void disassociate_ctty(int on_exit)
        current->signal->tty_old_pgrp = NULL;
        spin_unlock_irq(&current->sighand->siglock);
 
-       mutex_lock(&tty_mutex);
        tty = get_current_tty();
        if (tty) {
                unsigned long flags;
@@ -835,7 +848,6 @@ void disassociate_ctty(int on_exit)
                       " = NULL", tty);
 #endif
        }
-       mutex_unlock(&tty_mutex);
 
        /* Now clear signal->tty under the lock */
        read_lock(&tasklist_lock);
@@ -1215,7 +1227,8 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
  *     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
@@ -1236,7 +1249,7 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
  */
 
 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;
@@ -1267,6 +1280,11 @@ static int init_dev(struct tty_driver *driver, int idx,
        }
        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
@@ -1401,7 +1419,7 @@ static int init_dev(struct tty_driver *driver, int idx,
 
        if (retval)
                goto release_mem_out;
-        goto success;
+       goto success;
 
        /*
         * This fast open can be used if the tty is already open.
@@ -1464,6 +1482,31 @@ release_mem_out:
        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
@@ -1481,27 +1524,11 @@ static void release_one_tty(struct kref *kref)
 {
        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--;
@@ -1783,7 +1810,7 @@ static void release_dev(struct file *filp)
 }
 
 /**
- *     tty_open                -       open a tty device
+ *     __tty_open              -       open a tty device
  *     @inode: inode of device file
  *     @filp: file pointer to tty
  *
@@ -1862,7 +1889,7 @@ retry_open:
                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;
@@ -1959,7 +1986,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
                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)
@@ -3161,14 +3188,11 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 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(&current->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(&current->sighand->siglock, flags);
        return tty;
 }
 EXPORT_SYMBOL_GPL(get_current_tty);