diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-02-18 05:29:10 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-02-18 05:29:10 -0800 |
| commit | 7f1707cab227635e3bf400e19e25ef217dc28042 (patch) | |
| tree | 484572cc98f03998949988880a4ffa125dacbb3e | |
| parent | f5e31c2fd615aec21d8bfcb1b17938a6c7024355 (diff) | |
[PATCH] TTY module refcounting fix
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).
| -rw-r--r-- | drivers/char/tty_io.c | 16 | ||||
| -rw-r--r-- | include/linux/tty_ldisc.h | 3 |
2 files changed, 19 insertions, 0 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 8ec7f9d7e429..e39c8d0b2028 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -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]; } diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index ed2029741982..ac8ac46845ba 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -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 |
