summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-02-18 05:29:10 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-02-18 05:29:10 -0800
commit7f1707cab227635e3bf400e19e25ef217dc28042 (patch)
tree484572cc98f03998949988880a4ffa125dacbb3e
parentf5e31c2fd615aec21d8bfcb1b17938a6c7024355 (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.c16
-rw-r--r--include/linux/tty_ldisc.h3
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