aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/tty.h
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-06-11 07:50:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 11:51:01 -0400
commitc65c9bc3efa5589f691276bb9db689119a711222 (patch)
treeccb86ffb28ecafa77623fb2789faae8e4c1e2c4b /include/linux/tty.h
parente8b70e7d3e86319a8b2aaabde3866833d92cd80f (diff)
tty: rewrite the ldisc locking
There are several pretty much unfixable races in the old ldisc code, especially with respect to pty behaviour and also to hangup. It's easier to rewrite the code than simply try and patch it up. This patch - splits the ldisc from the tty (so we will be able to refcount it more cleanly later) - introduces a mutex lock for ldisc changing on an active device - fixes the complete mess that hangup caused - implements hopefully correct setldisc/close/hangup locking There are still some problems around pty pairs that have always been there but at least it is now possible to understand the code and fix further problems. This fixes the following known bugs - hang up can leak ldisc references - hang up may not call open/close on ldisc in a matched way - pty/tty pairs can deadlock during an ldisc change - reading the ldisc proc files can cause every ldisc to be loaded and probably a few other of the mysterious ldisc race reports. I'm sure it also adds the odd new one. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/tty.h')
-rw-r--r--include/linux/tty.h9
1 files changed, 7 insertions, 2 deletions
diff --git a/include/linux/tty.h b/include/linux/tty.h
index f9c13c83790c..1488d8c81aac 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -226,8 +226,11 @@ struct tty_struct {
226 struct tty_driver *driver; 226 struct tty_driver *driver;
227 const struct tty_operations *ops; 227 const struct tty_operations *ops;
228 int index; 228 int index;
229 /* The ldisc objects are protected by tty_ldisc_lock at the moment */ 229
230 struct tty_ldisc ldisc; 230 /* Protects ldisc changes: Lock tty not pty */
231 struct mutex ldisc_mutex;
232 struct tty_ldisc *ldisc;
233
231 struct mutex termios_mutex; 234 struct mutex termios_mutex;
232 spinlock_t ctrl_lock; 235 spinlock_t ctrl_lock;
233 /* Termios values are protected by the termios mutex */ 236 /* Termios values are protected by the termios mutex */
@@ -314,6 +317,7 @@ struct tty_struct {
314#define TTY_CLOSING 7 /* ->close() in progress */ 317#define TTY_CLOSING 7 /* ->close() in progress */
315#define TTY_LDISC 9 /* Line discipline attached */ 318#define TTY_LDISC 9 /* Line discipline attached */
316#define TTY_LDISC_CHANGING 10 /* Line discipline changing */ 319#define TTY_LDISC_CHANGING 10 /* Line discipline changing */
320#define TTY_LDISC_OPEN 11 /* Line discipline is open */
317#define TTY_HW_COOK_OUT 14 /* Hardware can do output cooking */ 321#define TTY_HW_COOK_OUT 14 /* Hardware can do output cooking */
318#define TTY_HW_COOK_IN 15 /* Hardware can do input cooking */ 322#define TTY_HW_COOK_IN 15 /* Hardware can do input cooking */
319#define TTY_PTY_LOCK 16 /* pty private */ 323#define TTY_PTY_LOCK 16 /* pty private */
@@ -406,6 +410,7 @@ extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
406extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); 410extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
407extern void tty_ldisc_deref(struct tty_ldisc *); 411extern void tty_ldisc_deref(struct tty_ldisc *);
408extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *); 412extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
413extern void tty_ldisc_hangup(struct tty_struct *tty);
409extern const struct file_operations tty_ldiscs_proc_fops; 414extern const struct file_operations tty_ldiscs_proc_fops;
410 415
411extern void tty_wakeup(struct tty_struct *tty); 416extern void tty_wakeup(struct tty_struct *tty);