diff options
author | David S. Miller <davem@davemloft.net> | 2009-12-11 17:12:17 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-11 17:12:17 -0800 |
commit | 501706565b2d4d2d40d0d301d5411ede099b8a6f (patch) | |
tree | 142a18bf1f1e74a09dbfa27540b893ade0fd797d /drivers/char/tty_ldisc.c | |
parent | e93737b0f0159a61772894943199fd3b6f315641 (diff) | |
parent | 2fe77b81c77eed92c4c0439f74c8148a295b4a86 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
include/net/tcp.h
Diffstat (limited to 'drivers/char/tty_ldisc.c')
-rw-r--r-- | drivers/char/tty_ldisc.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index feb55075819..3f653f7d849 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -34,6 +34,8 @@ #include <linux/vt_kern.h> #include <linux/selection.h> +#include <linux/smp_lock.h> /* For the moment */ + #include <linux/kmod.h> #include <linux/nsproxy.h> @@ -443,8 +445,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) { WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); - if (ld->ops->open) - return ld->ops->open(tty); + if (ld->ops->open) { + int ret; + /* BKL here locks verus a hangup event */ + lock_kernel(); + ret = ld->ops->open(tty); + unlock_kernel(); + return ret; + } return 0; } @@ -545,6 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); + lock_kernel(); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -558,10 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { + unlock_kernel(); tty_ldisc_put(new_ldisc); return 0; } + unlock_kernel(); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -582,6 +593,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); mutex_lock(&tty->ldisc_mutex); } + + lock_kernel(); + set_bit(TTY_LDISC_CHANGING, &tty->flags); /* @@ -592,6 +606,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty->receive_room = 0; o_ldisc = tty->ldisc; + + unlock_kernel(); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -617,12 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) flush_scheduled_work(); mutex_lock(&tty->ldisc_mutex); + lock_kernel(); if (test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); + unlock_kernel(); return -EIO; } @@ -664,6 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (o_work) schedule_delayed_work(&o_tty->buf.work, 1); mutex_unlock(&tty->ldisc_mutex); + unlock_kernel(); return retval; } |