]> git.hungrycats.org Git - linux/commitdiff
[PATCH] TTY module refcounting fix
authorAndrew Morton <akpm@digeo.com>
Tue, 18 Feb 2003 13:29:10 +0000 (05:29 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 18 Feb 2003 13:29:10 +0000 (05:29 -0800)
Patch from Max Krasnyansky <maxk@qualcomm.com>

This changeset adds module refcounting for TTY line disciplines.  I've sent
the patch to LKM earlier.  No negative comments (actually most people didn't
seem to care).  This is needed at least for Bluetooth and IrDA (Jean is ok
with the patch).

drivers/char/tty_io.c
include/linux/tty_ldisc.h

index 8ec7f9d7e429e84f7068f0f24b1e7f237968dbfb..e39c8d0b202801b5186761932f77c5d562b0277a 100644 (file)
@@ -286,6 +286,10 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
        if (tty->ldisc.num == ldisc)
                return 0;       /* We are already in the desired discipline */
+
+       if (!try_module_get(ldiscs[ldisc].owner))
+               return -EINVAL;
+       
        o_ldisc = tty->ldisc;
 
        tty_wait_until_sent(tty, 0);
@@ -300,9 +304,13 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
        if (tty->ldisc.open)
                retval = (tty->ldisc.open)(tty);
        if (retval < 0) {
+               module_put(tty->ldisc.owner);
+               
                tty->ldisc = o_ldisc;
                tty->termios->c_line = tty->ldisc.num;
                if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
+                       module_put(tty->ldisc.owner);
+
                        tty->ldisc = ldiscs[N_TTY];
                        tty->termios->c_line = N_TTY;
                        if (tty->ldisc.open) {
@@ -314,7 +322,10 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
                                              tty_name(tty, buf), r);
                        }
                }
+       } else {
+               module_put(o_ldisc.owner);
        }
+       
        if (tty->ldisc.num != o_ldisc.num && tty->driver.set_ldisc)
                tty->driver.set_ldisc(tty);
        return retval;
@@ -490,6 +501,8 @@ void do_tty_hangup(void *data)
        if (tty->ldisc.num != ldiscs[N_TTY].num) {
                if (tty->ldisc.close)
                        (tty->ldisc.close)(tty);
+               module_put(tty->ldisc.owner);
+               
                tty->ldisc = ldiscs[N_TTY];
                tty->termios->c_line = N_TTY;
                if (tty->ldisc.open) {
@@ -1268,11 +1281,14 @@ static void release_dev(struct file * filp)
         */
        if (tty->ldisc.close)
                (tty->ldisc.close)(tty);
+       module_put(tty->ldisc.owner);
+       
        tty->ldisc = ldiscs[N_TTY];
        tty->termios->c_line = N_TTY;
        if (o_tty) {
                if (o_tty->ldisc.close)
                        (o_tty->ldisc.close)(o_tty);
+               module_put(o_tty->ldisc.owner);
                o_tty->ldisc = ldiscs[N_TTY];
        }
        
index ed202974198228e431632bba7686b3cb1002e0c2..ac8ac46845ba0907f57d6a5879ceaf03cea3fe32 100644 (file)
@@ -105,6 +105,7 @@ struct tty_ldisc {
        char    *name;
        int     num;
        int     flags;
+       
        /*
         * The following routines are called from above.
         */
@@ -129,6 +130,8 @@ struct tty_ldisc {
                               char *fp, int count);
        int     (*receive_room)(struct tty_struct *);
        void    (*write_wakeup)(struct tty_struct *);
+
+       struct  module *owner;
 };
 
 #define TTY_LDISC_MAGIC        0x5403