aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-02-10 04:44:08 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:22 -0500
commitc6256c68248cfccbeec07ced442ffe395fa393e8 (patch)
tree24acdd2d3875680de114e8d50d50835b2705315b /arch/um/drivers/line.c
parentd5c9ffc6c6d15d4f655236e26942a21ad61fe3ad (diff)
[PATCH] uml: fix previous console locking
Eliminate the open_mutex after complaints from Blaisorblade. It turns out that the tty count provides the information needed to tell whether we are the first opener or last closer. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r--arch/um/drivers/line.c48
1 files changed, 8 insertions, 40 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 433e572fb196..0e1e9a20a4d6 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -425,42 +425,15 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
425 * However, in this case, mconsole requests can come in "from the 425 * However, in this case, mconsole requests can come in "from the
426 * side", and race with opens and closes. 426 * side", and race with opens and closes.
427 * 427 *
428 * The problem comes from line_setup not wanting to sleep if 428 * mconsole config requests will want to be sure the device isn't in
429 * the device is open or being opened. This can happen because the 429 * use, and get_config, open, and close will want a stable
430 * first opener of a device is responsible for setting it up on the 430 * configuration. The checking and modification of the configuration
431 * host, and that can sleep. The open of a port device will sleep 431 * is done under a spinlock. Checking whether the device is in use is
432 * until someone telnets to it. 432 * line->tty->count > 1, also under the spinlock.
433 * 433 *
434 * The obvious solution of putting everything under a mutex fails 434 * tty->count serves to decide whether the device should be enabled or
435 * because then trying (and failing) to change the configuration of an 435 * disabled on the host. If it's equal to 1, then we are doing the
436 * open(ing) device will block until the open finishes. The right 436 * first open or last close. Otherwise, open and close just return.
437 * thing to happen is for it to fail immediately.
438 *
439 * We can put the opening (and closing) of the host device under a
440 * separate lock, but that has to be taken before the count lock is
441 * released. Otherwise, you open a window in which another open can
442 * come through and assume that the host side is opened and working.
443 *
444 * So, if the tty count is one, open will take the open mutex
445 * inside the count lock. Otherwise, it just returns. This will sleep
446 * if the last close is pending, and will block a setup or get_config,
447 * but that should not last long.
448 *
449 * So, what we end up with is that open and close take the count lock.
450 * If the first open or last close are happening, then the open mutex
451 * is taken inside the count lock and the host opening or closing is done.
452 *
453 * setup and get_config only take the count lock. setup modifies the
454 * device configuration only if the open count is zero. Arbitrarily
455 * long blocking of setup doesn't happen because something would have to be
456 * waiting for an open to happen. However, a second open with
457 * tty->count == 1 can't happen, and a close can't happen until the open
458 * had finished.
459 *
460 * We can't maintain our own count here because the tty layer doesn't
461 * match opens and closes. It will call close if an open failed, and
462 * a tty hangup will result in excess closes. So, we rely on
463 * tty->count instead. It is one on both the first open and last close.
464 */ 437 */
465 438
466int line_open(struct line *lines, struct tty_struct *tty) 439int line_open(struct line *lines, struct tty_struct *tty)
@@ -476,7 +449,6 @@ int line_open(struct line *lines, struct tty_struct *tty)
476 if(tty->count > 1) 449 if(tty->count > 1)
477 goto out_unlock; 450 goto out_unlock;
478 451
479 mutex_lock(&line->open_mutex);
480 spin_unlock(&line->count_lock); 452 spin_unlock(&line->count_lock);
481 453
482 tty->driver_data = line; 454 tty->driver_data = line;
@@ -493,7 +465,6 @@ int line_open(struct line *lines, struct tty_struct *tty)
493 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 465 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
494 &tty->winsize.ws_col); 466 &tty->winsize.ws_col);
495 467
496 mutex_unlock(&line->open_mutex);
497 return err; 468 return err;
498 469
499out_unlock: 470out_unlock:
@@ -523,7 +494,6 @@ void line_close(struct tty_struct *tty, struct file * filp)
523 if(tty->count > 1) 494 if(tty->count > 1)
524 goto out_unlock; 495 goto out_unlock;
525 496
526 mutex_lock(&line->open_mutex);
527 spin_unlock(&line->count_lock); 497 spin_unlock(&line->count_lock);
528 498
529 line->tty = NULL; 499 line->tty = NULL;
@@ -534,7 +504,6 @@ void line_close(struct tty_struct *tty, struct file * filp)
534 line->sigio = 0; 504 line->sigio = 0;
535 } 505 }
536 506
537 mutex_unlock(&line->open_mutex);
538 return; 507 return;
539 508
540out_unlock: 509out_unlock:
@@ -755,7 +724,6 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
755 for(i = 0; i < nlines; i++){ 724 for(i = 0; i < nlines; i++){
756 line = &lines[i]; 725 line = &lines[i];
757 INIT_LIST_HEAD(&line->chan_list); 726 INIT_LIST_HEAD(&line->chan_list);
758 mutex_init(&line->open_mutex);
759 727
760 if(line->init_str == NULL) 728 if(line->init_str == NULL)
761 continue; 729 continue;