diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-06-15 07:04:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-23 19:38:34 -0400 |
commit | 36697529b5bbe36911e39a6309e7a7c9250d280a (patch) | |
tree | 5cbffa976994cb798e00d60eccb46c6cafc369a1 /drivers/tty | |
parent | d2c438905f9f718b3d9f5d89ce163fc22bd33995 (diff) |
tty: Replace ldisc locking with ldisc_sem
Line discipline locking was performed with a combination of
a mutex, a status bit, a count, and a waitqueue -- basically,
a rw semaphore.
Replace the existing combination with an ld_semaphore.
Fixes:
1) the 'reference acquire after ldisc locked' bug
2) the over-complicated halt mechanism
3) lock order wrt. tty_lock()
4) dropping locks while changing ldisc
5) previously unidentified deadlock while locking ldisc from
both linked ttys concurrently
6) previously unidentified recursive deadlocks
Adds much-needed lockdep diagnostics.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/tty_buffer.c | 2 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 7 | ||||
-rw-r--r-- | drivers/tty/tty_ldisc.c | 329 |
3 files changed, 50 insertions, 288 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 9121c1f7aeef..a42a028a9d4e 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -429,7 +429,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
429 | return; | 429 | return; |
430 | 430 | ||
431 | disc = tty_ldisc_ref(tty); | 431 | disc = tty_ldisc_ref(tty); |
432 | if (disc == NULL) /* !TTY_LDISC */ | 432 | if (disc == NULL) |
433 | return; | 433 | return; |
434 | 434 | ||
435 | spin_lock_irqsave(&buf->lock, flags); | 435 | spin_lock_irqsave(&buf->lock, flags); |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index fa80af3656a3..0fa5db4c7a7a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1388,8 +1388,7 @@ static int tty_reopen(struct tty_struct *tty) | |||
1388 | struct tty_driver *driver = tty->driver; | 1388 | struct tty_driver *driver = tty->driver; |
1389 | 1389 | ||
1390 | if (test_bit(TTY_CLOSING, &tty->flags) || | 1390 | if (test_bit(TTY_CLOSING, &tty->flags) || |
1391 | test_bit(TTY_HUPPING, &tty->flags) || | 1391 | test_bit(TTY_HUPPING, &tty->flags)) |
1392 | test_bit(TTY_LDISC_CHANGING, &tty->flags)) | ||
1393 | return -EIO; | 1392 | return -EIO; |
1394 | 1393 | ||
1395 | if (driver->type == TTY_DRIVER_TYPE_PTY && | 1394 | if (driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -1405,7 +1404,7 @@ static int tty_reopen(struct tty_struct *tty) | |||
1405 | } | 1404 | } |
1406 | tty->count++; | 1405 | tty->count++; |
1407 | 1406 | ||
1408 | WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); | 1407 | WARN_ON(!tty->ldisc); |
1409 | 1408 | ||
1410 | return 0; | 1409 | return 0; |
1411 | } | 1410 | } |
@@ -3017,7 +3016,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
3017 | tty->pgrp = NULL; | 3016 | tty->pgrp = NULL; |
3018 | mutex_init(&tty->legacy_mutex); | 3017 | mutex_init(&tty->legacy_mutex); |
3019 | mutex_init(&tty->termios_mutex); | 3018 | mutex_init(&tty->termios_mutex); |
3020 | mutex_init(&tty->ldisc_mutex); | 3019 | init_ldsem(&tty->ldisc_sem); |
3021 | init_waitqueue_head(&tty->write_wait); | 3020 | init_waitqueue_head(&tty->write_wait); |
3022 | init_waitqueue_head(&tty->read_wait); | 3021 | init_waitqueue_head(&tty->read_wait); |
3023 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 3022 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 418c9f64a9fd..b7b8048f1253 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -45,7 +45,6 @@ enum { | |||
45 | */ | 45 | */ |
46 | 46 | ||
47 | static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock); | 47 | static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock); |
48 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | ||
49 | /* Line disc dispatch table */ | 48 | /* Line disc dispatch table */ |
50 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; | 49 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; |
51 | 50 | ||
@@ -153,7 +152,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops) | |||
153 | * takes tty_ldiscs_lock to guard against ldisc races | 152 | * takes tty_ldiscs_lock to guard against ldisc races |
154 | */ | 153 | */ |
155 | 154 | ||
156 | static struct tty_ldisc *tty_ldisc_get(int disc) | 155 | static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) |
157 | { | 156 | { |
158 | struct tty_ldisc *ld; | 157 | struct tty_ldisc *ld; |
159 | struct tty_ldisc_ops *ldops; | 158 | struct tty_ldisc_ops *ldops; |
@@ -180,8 +179,7 @@ static struct tty_ldisc *tty_ldisc_get(int disc) | |||
180 | } | 179 | } |
181 | 180 | ||
182 | ld->ops = ldops; | 181 | ld->ops = ldops; |
183 | atomic_set(&ld->users, 1); | 182 | ld->tty = tty; |
184 | init_waitqueue_head(&ld->wq_idle); | ||
185 | 183 | ||
186 | return ld; | 184 | return ld; |
187 | } | 185 | } |
@@ -193,20 +191,11 @@ static struct tty_ldisc *tty_ldisc_get(int disc) | |||
193 | */ | 191 | */ |
194 | static inline void tty_ldisc_put(struct tty_ldisc *ld) | 192 | static inline void tty_ldisc_put(struct tty_ldisc *ld) |
195 | { | 193 | { |
196 | unsigned long flags; | ||
197 | |||
198 | if (WARN_ON_ONCE(!ld)) | 194 | if (WARN_ON_ONCE(!ld)) |
199 | return; | 195 | return; |
200 | 196 | ||
201 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); | 197 | put_ldops(ld->ops); |
202 | |||
203 | /* unreleased reader reference(s) will cause this WARN */ | ||
204 | WARN_ON(!atomic_dec_and_test(&ld->users)); | ||
205 | |||
206 | ld->ops->refcount--; | ||
207 | module_put(ld->ops->owner); | ||
208 | kfree(ld); | 198 | kfree(ld); |
209 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); | ||
210 | } | 199 | } |
211 | 200 | ||
212 | static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) | 201 | static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
@@ -258,34 +247,6 @@ const struct file_operations tty_ldiscs_proc_fops = { | |||
258 | }; | 247 | }; |
259 | 248 | ||
260 | /** | 249 | /** |
261 | * tty_ldisc_try - internal helper | ||
262 | * @tty: the tty | ||
263 | * | ||
264 | * Make a single attempt to grab and bump the refcount on | ||
265 | * the tty ldisc. Return 0 on failure or 1 on success. This is | ||
266 | * used to implement both the waiting and non waiting versions | ||
267 | * of tty_ldisc_ref | ||
268 | * | ||
269 | * Locking: takes tty_ldiscs_lock | ||
270 | */ | ||
271 | |||
272 | static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) | ||
273 | { | ||
274 | unsigned long flags; | ||
275 | struct tty_ldisc *ld; | ||
276 | |||
277 | /* FIXME: this allows reference acquire after TTY_LDISC is cleared */ | ||
278 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); | ||
279 | ld = NULL; | ||
280 | if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) { | ||
281 | ld = tty->ldisc; | ||
282 | atomic_inc(&ld->users); | ||
283 | } | ||
284 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); | ||
285 | return ld; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * tty_ldisc_ref_wait - wait for the tty ldisc | 250 | * tty_ldisc_ref_wait - wait for the tty ldisc |
290 | * @tty: tty device | 251 | * @tty: tty device |
291 | * | 252 | * |
@@ -298,16 +259,15 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) | |||
298 | * against a discipline change, such as an existing ldisc reference | 259 | * against a discipline change, such as an existing ldisc reference |
299 | * (which we check for) | 260 | * (which we check for) |
300 | * | 261 | * |
301 | * Locking: call functions take tty_ldiscs_lock | 262 | * Note: only callable from a file_operations routine (which |
263 | * guarantees tty->ldisc != NULL when the lock is acquired). | ||
302 | */ | 264 | */ |
303 | 265 | ||
304 | struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | 266 | struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) |
305 | { | 267 | { |
306 | struct tty_ldisc *ld; | 268 | ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT); |
307 | 269 | WARN_ON(!tty->ldisc); | |
308 | /* wait_event is a macro */ | 270 | return tty->ldisc; |
309 | wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL); | ||
310 | return ld; | ||
311 | } | 271 | } |
312 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | 272 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); |
313 | 273 | ||
@@ -318,13 +278,18 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | |||
318 | * Dereference the line discipline for the terminal and take a | 278 | * Dereference the line discipline for the terminal and take a |
319 | * reference to it. If the line discipline is in flux then | 279 | * reference to it. If the line discipline is in flux then |
320 | * return NULL. Can be called from IRQ and timer functions. | 280 | * return NULL. Can be called from IRQ and timer functions. |
321 | * | ||
322 | * Locking: called functions take tty_ldiscs_lock | ||
323 | */ | 281 | */ |
324 | 282 | ||
325 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) | 283 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) |
326 | { | 284 | { |
327 | return tty_ldisc_try(tty); | 285 | struct tty_ldisc *ld = NULL; |
286 | |||
287 | if (ldsem_down_read_trylock(&tty->ldisc_sem)) { | ||
288 | ld = tty->ldisc; | ||
289 | if (!ld) | ||
290 | ldsem_up_read(&tty->ldisc_sem); | ||
291 | } | ||
292 | return ld; | ||
328 | } | 293 | } |
329 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); | 294 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); |
330 | 295 | ||
@@ -334,27 +299,11 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref); | |||
334 | * | 299 | * |
335 | * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May | 300 | * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May |
336 | * be called in IRQ context. | 301 | * be called in IRQ context. |
337 | * | ||
338 | * Locking: takes tty_ldiscs_lock | ||
339 | */ | 302 | */ |
340 | 303 | ||
341 | void tty_ldisc_deref(struct tty_ldisc *ld) | 304 | void tty_ldisc_deref(struct tty_ldisc *ld) |
342 | { | 305 | { |
343 | unsigned long flags; | 306 | ldsem_up_read(&ld->tty->ldisc_sem); |
344 | |||
345 | if (WARN_ON_ONCE(!ld)) | ||
346 | return; | ||
347 | |||
348 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); | ||
349 | /* | ||
350 | * WARNs if one-too-many reader references were released | ||
351 | * - the last reference must be released with tty_ldisc_put | ||
352 | */ | ||
353 | WARN_ON(atomic_dec_and_test(&ld->users)); | ||
354 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); | ||
355 | |||
356 | if (waitqueue_active(&ld->wq_idle)) | ||
357 | wake_up(&ld->wq_idle); | ||
358 | } | 307 | } |
359 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); | 308 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); |
360 | 309 | ||
@@ -437,27 +386,6 @@ static void __lockfunc tty_ldisc_enable_pair(struct tty_struct *tty, | |||
437 | tty_ldisc_unlock_pair(tty, tty2); | 386 | tty_ldisc_unlock_pair(tty, tty2); |
438 | } | 387 | } |
439 | 388 | ||
440 | |||
441 | /** | ||
442 | * tty_ldisc_enable - allow ldisc use | ||
443 | * @tty: terminal to activate ldisc on | ||
444 | * | ||
445 | * Set the TTY_LDISC flag when the line discipline can be called | ||
446 | * again. Do necessary wakeups for existing sleepers. Clear the LDISC | ||
447 | * changing flag to indicate any ldisc change is now over. | ||
448 | * | ||
449 | * Note: nobody should set the TTY_LDISC bit except via this function. | ||
450 | * Clearing directly is allowed. | ||
451 | */ | ||
452 | |||
453 | static void tty_ldisc_enable(struct tty_struct *tty) | ||
454 | { | ||
455 | clear_bit(TTY_LDISC_HALTED, &tty->flags); | ||
456 | set_bit(TTY_LDISC, &tty->flags); | ||
457 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
458 | wake_up(&tty_ldisc_wait); | ||
459 | } | ||
460 | |||
461 | /** | 389 | /** |
462 | * tty_ldisc_flush - flush line discipline queue | 390 | * tty_ldisc_flush - flush line discipline queue |
463 | * @tty: tty | 391 | * @tty: tty |
@@ -555,14 +483,14 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | |||
555 | int r; | 483 | int r; |
556 | 484 | ||
557 | /* There is an outstanding reference here so this is safe */ | 485 | /* There is an outstanding reference here so this is safe */ |
558 | old = tty_ldisc_get(old->ops->num); | 486 | old = tty_ldisc_get(tty, old->ops->num); |
559 | WARN_ON(IS_ERR(old)); | 487 | WARN_ON(IS_ERR(old)); |
560 | tty->ldisc = old; | 488 | tty->ldisc = old; |
561 | tty_set_termios_ldisc(tty, old->ops->num); | 489 | tty_set_termios_ldisc(tty, old->ops->num); |
562 | if (tty_ldisc_open(tty, old) < 0) { | 490 | if (tty_ldisc_open(tty, old) < 0) { |
563 | tty_ldisc_put(old); | 491 | tty_ldisc_put(old); |
564 | /* This driver is always present */ | 492 | /* This driver is always present */ |
565 | new_ldisc = tty_ldisc_get(N_TTY); | 493 | new_ldisc = tty_ldisc_get(tty, N_TTY); |
566 | if (IS_ERR(new_ldisc)) | 494 | if (IS_ERR(new_ldisc)) |
567 | panic("n_tty: get"); | 495 | panic("n_tty: get"); |
568 | tty->ldisc = new_ldisc; | 496 | tty->ldisc = new_ldisc; |
@@ -576,101 +504,6 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | |||
576 | } | 504 | } |
577 | 505 | ||
578 | /** | 506 | /** |
579 | * tty_ldisc_wait_idle - wait for the ldisc to become idle | ||
580 | * @tty: tty to wait for | ||
581 | * @timeout: for how long to wait at most | ||
582 | * | ||
583 | * Wait for the line discipline to become idle. The discipline must | ||
584 | * have been halted for this to guarantee it remains idle. | ||
585 | */ | ||
586 | static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) | ||
587 | { | ||
588 | long ret; | ||
589 | ret = wait_event_timeout(tty->ldisc->wq_idle, | ||
590 | atomic_read(&tty->ldisc->users) == 1, timeout); | ||
591 | return ret > 0 ? 0 : -EBUSY; | ||
592 | } | ||
593 | |||
594 | /** | ||
595 | * tty_ldisc_halt - shut down the line discipline | ||
596 | * @tty: tty device | ||
597 | * @o_tty: paired pty device (can be NULL) | ||
598 | * @timeout: # of jiffies to wait for ldisc refs to be released | ||
599 | * | ||
600 | * Shut down the line discipline and work queue for this tty device and | ||
601 | * its paired pty (if exists). Clearing the TTY_LDISC flag ensures | ||
602 | * no further references can be obtained, while waiting for existing | ||
603 | * references to be released ensures no more data is fed to the ldisc. | ||
604 | * | ||
605 | * You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex) | ||
606 | * in order to make sure any currently executing ldisc work is also | ||
607 | * flushed. | ||
608 | */ | ||
609 | |||
610 | static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty, | ||
611 | long timeout) | ||
612 | { | ||
613 | int retval; | ||
614 | |||
615 | clear_bit(TTY_LDISC, &tty->flags); | ||
616 | if (o_tty) | ||
617 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
618 | |||
619 | retval = tty_ldisc_wait_idle(tty, timeout); | ||
620 | if (!retval && o_tty) | ||
621 | retval = tty_ldisc_wait_idle(o_tty, timeout); | ||
622 | if (retval) | ||
623 | return retval; | ||
624 | |||
625 | set_bit(TTY_LDISC_HALTED, &tty->flags); | ||
626 | if (o_tty) | ||
627 | set_bit(TTY_LDISC_HALTED, &o_tty->flags); | ||
628 | |||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * tty_ldisc_hangup_halt - halt the line discipline for hangup | ||
634 | * @tty: tty being hung up | ||
635 | * | ||
636 | * Shut down the line discipline and work queue for the tty device | ||
637 | * being hungup. Clear the TTY_LDISC flag to ensure no further | ||
638 | * references can be obtained and wait for remaining references to be | ||
639 | * released to ensure no more data is fed to this ldisc. | ||
640 | * Caller must hold legacy and ->ldisc_mutex. | ||
641 | * | ||
642 | * NB: tty_set_ldisc() is prevented from changing the ldisc concurrently | ||
643 | * with this function by checking the TTY_HUPPING flag. | ||
644 | */ | ||
645 | static bool tty_ldisc_hangup_halt(struct tty_struct *tty) | ||
646 | { | ||
647 | char cur_n[TASK_COMM_LEN], tty_n[64]; | ||
648 | long timeout = 3 * HZ; | ||
649 | |||
650 | clear_bit(TTY_LDISC, &tty->flags); | ||
651 | |||
652 | if (tty->ldisc) { /* Not yet closed */ | ||
653 | tty_unlock(tty); | ||
654 | |||
655 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { | ||
656 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
657 | printk_ratelimited(KERN_WARNING | ||
658 | "%s: waiting (%s) for %s took too long, but we keep waiting...\n", | ||
659 | __func__, get_task_comm(cur_n, current), | ||
660 | tty_name(tty, tty_n)); | ||
661 | } | ||
662 | |||
663 | set_bit(TTY_LDISC_HALTED, &tty->flags); | ||
664 | |||
665 | /* must reacquire both locks and preserve lock order */ | ||
666 | mutex_unlock(&tty->ldisc_mutex); | ||
667 | tty_lock(tty); | ||
668 | mutex_lock(&tty->ldisc_mutex); | ||
669 | } | ||
670 | return !!tty->ldisc; | ||
671 | } | ||
672 | |||
673 | /** | ||
674 | * tty_set_ldisc - set line discipline | 507 | * tty_set_ldisc - set line discipline |
675 | * @tty: the terminal to set | 508 | * @tty: the terminal to set |
676 | * @ldisc: the line discipline | 509 | * @ldisc: the line discipline |
@@ -679,103 +512,47 @@ static bool tty_ldisc_hangup_halt(struct tty_struct *tty) | |||
679 | * context. The ldisc change logic has to protect itself against any | 512 | * context. The ldisc change logic has to protect itself against any |
680 | * overlapping ldisc change (including on the other end of pty pairs), | 513 | * overlapping ldisc change (including on the other end of pty pairs), |
681 | * the close of one side of a tty/pty pair, and eventually hangup. | 514 | * the close of one side of a tty/pty pair, and eventually hangup. |
682 | * | ||
683 | * Locking: takes tty_ldiscs_lock, termios_mutex | ||
684 | */ | 515 | */ |
685 | 516 | ||
686 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) | 517 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) |
687 | { | 518 | { |
688 | int retval; | 519 | int retval; |
689 | struct tty_ldisc *o_ldisc, *new_ldisc; | 520 | struct tty_ldisc *o_ldisc, *new_ldisc; |
690 | struct tty_struct *o_tty; | 521 | struct tty_struct *o_tty = tty->link; |
691 | 522 | ||
692 | new_ldisc = tty_ldisc_get(ldisc); | 523 | new_ldisc = tty_ldisc_get(tty, ldisc); |
693 | if (IS_ERR(new_ldisc)) | 524 | if (IS_ERR(new_ldisc)) |
694 | return PTR_ERR(new_ldisc); | 525 | return PTR_ERR(new_ldisc); |
695 | 526 | ||
696 | tty_lock(tty); | 527 | retval = tty_ldisc_lock_pair_timeout(tty, o_tty, 5 * HZ); |
697 | /* | 528 | if (retval) { |
698 | * We need to look at the tty locking here for pty/tty pairs | 529 | tty_ldisc_put(new_ldisc); |
699 | * when both sides try to change in parallel. | 530 | return retval; |
700 | */ | 531 | } |
701 | |||
702 | o_tty = tty->link; /* o_tty is the pty side or NULL */ | ||
703 | |||
704 | 532 | ||
705 | /* | 533 | /* |
706 | * Check the no-op case | 534 | * Check the no-op case |
707 | */ | 535 | */ |
708 | 536 | ||
709 | if (tty->ldisc->ops->num == ldisc) { | 537 | if (tty->ldisc->ops->num == ldisc) { |
710 | tty_unlock(tty); | 538 | tty_ldisc_enable_pair(tty, o_tty); |
711 | tty_ldisc_put(new_ldisc); | 539 | tty_ldisc_put(new_ldisc); |
712 | return 0; | 540 | return 0; |
713 | } | 541 | } |
714 | 542 | ||
715 | mutex_lock(&tty->ldisc_mutex); | 543 | /* FIXME: why 'shutoff' input if the ldisc is locked? */ |
716 | |||
717 | /* | ||
718 | * We could be midstream of another ldisc change which has | ||
719 | * dropped the lock during processing. If so we need to wait. | ||
720 | */ | ||
721 | |||
722 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
723 | mutex_unlock(&tty->ldisc_mutex); | ||
724 | tty_unlock(tty); | ||
725 | wait_event(tty_ldisc_wait, | ||
726 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | ||
727 | tty_lock(tty); | ||
728 | mutex_lock(&tty->ldisc_mutex); | ||
729 | } | ||
730 | |||
731 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
732 | |||
733 | /* | ||
734 | * No more input please, we are switching. The new ldisc | ||
735 | * will update this value in the ldisc open function | ||
736 | */ | ||
737 | |||
738 | tty->receive_room = 0; | 544 | tty->receive_room = 0; |
739 | 545 | ||
740 | o_ldisc = tty->ldisc; | 546 | o_ldisc = tty->ldisc; |
741 | |||
742 | tty_unlock(tty); | ||
743 | /* | ||
744 | * Make sure we don't change while someone holds a | ||
745 | * reference to the line discipline. The TTY_LDISC bit | ||
746 | * prevents anyone taking a reference once it is clear. | ||
747 | * We need the lock to avoid racing reference takers. | ||
748 | * | ||
749 | * We must clear the TTY_LDISC bit here to avoid a livelock | ||
750 | * with a userspace app continually trying to use the tty in | ||
751 | * parallel to the change and re-referencing the tty. | ||
752 | */ | ||
753 | |||
754 | retval = tty_ldisc_halt(tty, o_tty, 5 * HZ); | ||
755 | |||
756 | /* | ||
757 | * Wait for hangup to complete, if pending. | ||
758 | * We must drop the mutex here in case a hangup is also in process. | ||
759 | */ | ||
760 | |||
761 | mutex_unlock(&tty->ldisc_mutex); | ||
762 | |||
763 | flush_work(&tty->hangup_work); | ||
764 | |||
765 | tty_lock(tty); | 547 | tty_lock(tty); |
766 | mutex_lock(&tty->ldisc_mutex); | ||
767 | 548 | ||
768 | /* handle wait idle failure locked */ | 549 | /* FIXME: for testing only */ |
769 | if (retval) { | 550 | WARN_ON(test_bit(TTY_HUPPED, &tty->flags)); |
770 | tty_ldisc_put(new_ldisc); | ||
771 | goto enable; | ||
772 | } | ||
773 | 551 | ||
774 | if (test_bit(TTY_HUPPING, &tty->flags)) { | 552 | if (test_bit(TTY_HUPPING, &tty->flags)) { |
775 | /* We were raced by the hangup method. It will have stomped | 553 | /* We were raced by the hangup method. It will have stomped |
776 | the ldisc data and closed the ldisc down */ | 554 | the ldisc data and closed the ldisc down */ |
777 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 555 | tty_ldisc_enable_pair(tty, o_tty); |
778 | mutex_unlock(&tty->ldisc_mutex); | ||
779 | tty_ldisc_put(new_ldisc); | 556 | tty_ldisc_put(new_ldisc); |
780 | tty_unlock(tty); | 557 | tty_unlock(tty); |
781 | return -EIO; | 558 | return -EIO; |
@@ -804,14 +581,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
804 | 581 | ||
805 | tty_ldisc_put(o_ldisc); | 582 | tty_ldisc_put(o_ldisc); |
806 | 583 | ||
807 | enable: | ||
808 | /* | 584 | /* |
809 | * Allow ldisc referencing to occur again | 585 | * Allow ldisc referencing to occur again |
810 | */ | 586 | */ |
811 | 587 | tty_ldisc_enable_pair(tty, o_tty); | |
812 | tty_ldisc_enable(tty); | ||
813 | if (o_tty) | ||
814 | tty_ldisc_enable(o_tty); | ||
815 | 588 | ||
816 | /* Restart the work queue in case no characters kick it off. Safe if | 589 | /* Restart the work queue in case no characters kick it off. Safe if |
817 | already running */ | 590 | already running */ |
@@ -819,7 +592,6 @@ enable: | |||
819 | if (o_tty) | 592 | if (o_tty) |
820 | schedule_work(&o_tty->port->buf.work); | 593 | schedule_work(&o_tty->port->buf.work); |
821 | 594 | ||
822 | mutex_unlock(&tty->ldisc_mutex); | ||
823 | tty_unlock(tty); | 595 | tty_unlock(tty); |
824 | return retval; | 596 | return retval; |
825 | } | 597 | } |
@@ -852,7 +624,7 @@ static void tty_reset_termios(struct tty_struct *tty) | |||
852 | 624 | ||
853 | static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) | 625 | static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) |
854 | { | 626 | { |
855 | struct tty_ldisc *ld = tty_ldisc_get(ldisc); | 627 | struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc); |
856 | 628 | ||
857 | if (IS_ERR(ld)) | 629 | if (IS_ERR(ld)) |
858 | return -1; | 630 | return -1; |
@@ -891,14 +663,8 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
891 | 663 | ||
892 | tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); | 664 | tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); |
893 | 665 | ||
894 | /* | ||
895 | * FIXME! What are the locking issues here? This may me overdoing | ||
896 | * things... This question is especially important now that we've | ||
897 | * removed the irqlock. | ||
898 | */ | ||
899 | ld = tty_ldisc_ref(tty); | 666 | ld = tty_ldisc_ref(tty); |
900 | if (ld != NULL) { | 667 | if (ld != NULL) { |
901 | /* We may have no line discipline at this point */ | ||
902 | if (ld->ops->flush_buffer) | 668 | if (ld->ops->flush_buffer) |
903 | ld->ops->flush_buffer(tty); | 669 | ld->ops->flush_buffer(tty); |
904 | tty_driver_flush_buffer(tty); | 670 | tty_driver_flush_buffer(tty); |
@@ -909,21 +675,22 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
909 | ld->ops->hangup(tty); | 675 | ld->ops->hangup(tty); |
910 | tty_ldisc_deref(ld); | 676 | tty_ldisc_deref(ld); |
911 | } | 677 | } |
912 | /* | 678 | |
913 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
914 | * ldisc completion and fix the driver call race | ||
915 | */ | ||
916 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | 679 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
917 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | 680 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
681 | |||
682 | tty_unlock(tty); | ||
683 | |||
918 | /* | 684 | /* |
919 | * Shutdown the current line discipline, and reset it to | 685 | * Shutdown the current line discipline, and reset it to |
920 | * N_TTY if need be. | 686 | * N_TTY if need be. |
921 | * | 687 | * |
922 | * Avoid racing set_ldisc or tty_ldisc_release | 688 | * Avoid racing set_ldisc or tty_ldisc_release |
923 | */ | 689 | */ |
924 | mutex_lock(&tty->ldisc_mutex); | 690 | tty_ldisc_lock_pair(tty, tty->link); |
691 | tty_lock(tty); | ||
925 | 692 | ||
926 | if (tty_ldisc_hangup_halt(tty)) { | 693 | if (tty->ldisc) { |
927 | 694 | ||
928 | /* At this point we have a halted ldisc; we want to close it and | 695 | /* At this point we have a halted ldisc; we want to close it and |
929 | reopen a new ldisc. We could defer the reopen to the next | 696 | reopen a new ldisc. We could defer the reopen to the next |
@@ -942,9 +709,8 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
942 | BUG_ON(tty_ldisc_reinit(tty, N_TTY)); | 709 | BUG_ON(tty_ldisc_reinit(tty, N_TTY)); |
943 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | 710 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); |
944 | } | 711 | } |
945 | tty_ldisc_enable(tty); | ||
946 | } | 712 | } |
947 | mutex_unlock(&tty->ldisc_mutex); | 713 | tty_ldisc_enable_pair(tty, tty->link); |
948 | if (reset) | 714 | if (reset) |
949 | tty_reset_termios(tty); | 715 | tty_reset_termios(tty); |
950 | 716 | ||
@@ -976,15 +742,12 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | |||
976 | tty_ldisc_close(tty, ld); | 742 | tty_ldisc_close(tty, ld); |
977 | return retval; | 743 | return retval; |
978 | } | 744 | } |
979 | tty_ldisc_enable(o_tty); | ||
980 | } | 745 | } |
981 | tty_ldisc_enable(tty); | ||
982 | return 0; | 746 | return 0; |
983 | } | 747 | } |
984 | 748 | ||
985 | static void tty_ldisc_kill(struct tty_struct *tty) | 749 | static void tty_ldisc_kill(struct tty_struct *tty) |
986 | { | 750 | { |
987 | mutex_lock(&tty->ldisc_mutex); | ||
988 | /* | 751 | /* |
989 | * Now kill off the ldisc | 752 | * Now kill off the ldisc |
990 | */ | 753 | */ |
@@ -995,7 +758,6 @@ static void tty_ldisc_kill(struct tty_struct *tty) | |||
995 | 758 | ||
996 | /* Ensure the next open requests the N_TTY ldisc */ | 759 | /* Ensure the next open requests the N_TTY ldisc */ |
997 | tty_set_termios_ldisc(tty, N_TTY); | 760 | tty_set_termios_ldisc(tty, N_TTY); |
998 | mutex_unlock(&tty->ldisc_mutex); | ||
999 | } | 761 | } |
1000 | 762 | ||
1001 | /** | 763 | /** |
@@ -1017,15 +779,16 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
1017 | 779 | ||
1018 | tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); | 780 | tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); |
1019 | 781 | ||
1020 | tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT); | 782 | tty_ldisc_lock_pair(tty, o_tty); |
1021 | |||
1022 | tty_lock_pair(tty, o_tty); | 783 | tty_lock_pair(tty, o_tty); |
1023 | /* This will need doing differently if we need to lock */ | 784 | |
1024 | tty_ldisc_kill(tty); | 785 | tty_ldisc_kill(tty); |
1025 | if (o_tty) | 786 | if (o_tty) |
1026 | tty_ldisc_kill(o_tty); | 787 | tty_ldisc_kill(o_tty); |
1027 | 788 | ||
1028 | tty_unlock_pair(tty, o_tty); | 789 | tty_unlock_pair(tty, o_tty); |
790 | tty_ldisc_unlock_pair(tty, o_tty); | ||
791 | |||
1029 | /* And the memory resources remaining (buffers, termios) will be | 792 | /* And the memory resources remaining (buffers, termios) will be |
1030 | disposed of when the kref hits zero */ | 793 | disposed of when the kref hits zero */ |
1031 | 794 | ||
@@ -1042,7 +805,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
1042 | 805 | ||
1043 | void tty_ldisc_init(struct tty_struct *tty) | 806 | void tty_ldisc_init(struct tty_struct *tty) |
1044 | { | 807 | { |
1045 | struct tty_ldisc *ld = tty_ldisc_get(N_TTY); | 808 | struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); |
1046 | if (IS_ERR(ld)) | 809 | if (IS_ERR(ld)) |
1047 | panic("n_tty: init_tty"); | 810 | panic("n_tty: init_tty"); |
1048 | tty->ldisc = ld; | 811 | tty->ldisc = ld; |