aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-09-09 17:36:37 -0400
committerRichard Weinberger <richard@nod.at>2012-03-24 19:29:53 -0400
commitd8c215adbf3901aa7d00a0f17f08d77be689f838 (patch)
tree88f7f49abb5944725f3b60d8f28a41580e7f915f
parent43574c1afea4f798592c03cf4d4ecea4fd0a8416 (diff)
um: convert count_lock to mutex, fix a race in line_open()
If two processes are opening the same line, the second to get into line_open() will decide that it doesn't need to do anything (correctly) or wait for anything. The latter, unfortunately, is incorrect - the first opener might not be through yet. We need to have exclusion covering the entire line_init(), including the blocking parts. Moreover, the next patch will need to widen the exclusion on mconsole side of things, also including the blocking bits, so let's just convert that sucker to mutex... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r--arch/um/drivers/line.c26
-rw-r--r--arch/um/drivers/line.h2
-rw-r--r--arch/um/drivers/ssl.c2
-rw-r--r--arch/um/drivers/stdio_console.c2
4 files changed, 12 insertions, 20 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 3eea99e98a11..dc7e216df6a5 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -409,7 +409,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
409 struct line *line = &lines[tty->index]; 409 struct line *line = &lines[tty->index];
410 int err = -ENODEV; 410 int err = -ENODEV;
411 411
412 spin_lock(&line->count_lock); 412 mutex_lock(&line->count_lock);
413 if (!line->valid) 413 if (!line->valid)
414 goto out_unlock; 414 goto out_unlock;
415 415
@@ -421,10 +421,9 @@ int line_open(struct line *lines, struct tty_struct *tty)
421 tty->driver_data = line; 421 tty->driver_data = line;
422 line->tty = tty; 422 line->tty = tty;
423 423
424 spin_unlock(&line->count_lock);
425 err = enable_chan(line); 424 err = enable_chan(line);
426 if (err) /* line_close() will be called by our caller */ 425 if (err) /* line_close() will be called by our caller */
427 return err; 426 goto out_unlock;
428 427
429 INIT_DELAYED_WORK(&line->task, line_timer_cb); 428 INIT_DELAYED_WORK(&line->task, line_timer_cb);
430 429
@@ -435,11 +434,8 @@ int line_open(struct line *lines, struct tty_struct *tty)
435 434
436 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 435 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
437 &tty->winsize.ws_col); 436 &tty->winsize.ws_col);
438
439 return 0;
440
441out_unlock: 437out_unlock:
442 spin_unlock(&line->count_lock); 438 mutex_unlock(&line->count_lock);
443 return err; 439 return err;
444} 440}
445 441
@@ -459,7 +455,7 @@ void line_close(struct tty_struct *tty, struct file * filp)
459 /* We ignore the error anyway! */ 455 /* We ignore the error anyway! */
460 flush_buffer(line); 456 flush_buffer(line);
461 457
462 spin_lock(&line->count_lock); 458 mutex_lock(&line->count_lock);
463 BUG_ON(!line->valid); 459 BUG_ON(!line->valid);
464 460
465 if (--line->count) 461 if (--line->count)
@@ -468,17 +464,13 @@ void line_close(struct tty_struct *tty, struct file * filp)
468 line->tty = NULL; 464 line->tty = NULL;
469 tty->driver_data = NULL; 465 tty->driver_data = NULL;
470 466
471 spin_unlock(&line->count_lock);
472
473 if (line->sigio) { 467 if (line->sigio) {
474 unregister_winch(tty); 468 unregister_winch(tty);
475 line->sigio = 0; 469 line->sigio = 0;
476 } 470 }
477 471
478 return;
479
480out_unlock: 472out_unlock:
481 spin_unlock(&line->count_lock); 473 mutex_unlock(&line->count_lock);
482} 474}
483 475
484void close_lines(struct line *lines, int nlines) 476void close_lines(struct line *lines, int nlines)
@@ -495,7 +487,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
495 struct line *line = &lines[n]; 487 struct line *line = &lines[n];
496 int err = -EINVAL; 488 int err = -EINVAL;
497 489
498 spin_lock(&line->count_lock); 490 mutex_lock(&line->count_lock);
499 491
500 if (line->count) { 492 if (line->count) {
501 *error_out = "Device is already open"; 493 *error_out = "Device is already open";
@@ -510,7 +502,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
510 } 502 }
511 err = 0; 503 err = 0;
512out: 504out:
513 spin_unlock(&line->count_lock); 505 mutex_unlock(&line->count_lock);
514 return err; 506 return err;
515} 507}
516 508
@@ -609,13 +601,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
609 601
610 line = &lines[dev]; 602 line = &lines[dev];
611 603
612 spin_lock(&line->count_lock); 604 mutex_lock(&line->count_lock);
613 if (!line->valid) 605 if (!line->valid)
614 CONFIG_CHUNK(str, size, n, "none", 1); 606 CONFIG_CHUNK(str, size, n, "none", 1);
615 else if (line->tty == NULL) 607 else if (line->tty == NULL)
616 CONFIG_CHUNK(str, size, n, line->init_str, 1); 608 CONFIG_CHUNK(str, size, n, line->init_str, 1);
617 else n = chan_config_string(&line->chan_list, str, size, error_out); 609 else n = chan_config_string(&line->chan_list, str, size, error_out);
618 spin_unlock(&line->count_lock); 610 mutex_unlock(&line->count_lock);
619 611
620 return n; 612 return n;
621} 613}
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 0c4dadf5e03e..471f477b271e 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -32,7 +32,7 @@ struct line_driver {
32 32
33struct line { 33struct line {
34 struct tty_struct *tty; 34 struct tty_struct *tty;
35 spinlock_t count_lock; 35 struct mutex count_lock;
36 unsigned long count; 36 unsigned long count;
37 int valid; 37 int valid;
38 38
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 445288ff0650..23cffd6d85af 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -201,7 +201,7 @@ static int ssl_init(void)
201 serial_lines[i].valid = 1; 201 serial_lines[i].valid = 1;
202 } 202 }
203 spin_lock_init(&serial_lines[i].lock); 203 spin_lock_init(&serial_lines[i].lock);
204 spin_lock_init(&serial_lines[i].count_lock); 204 mutex_init(&serial_lines[i].count_lock);
205 serial_lines[i].driver = &driver; 205 serial_lines[i].driver = &driver;
206 } 206 }
207 ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, 207 ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 6d244f470968..f8d4325b28b7 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -173,7 +173,7 @@ static int stdio_init(void)
173 vts[i].valid = 1; 173 vts[i].valid = 1;
174 } 174 }
175 spin_lock_init(&vts[i].lock); 175 spin_lock_init(&vts[i].lock);
176 spin_lock_init(&vts[i].count_lock); 176 mutex_init(&vts[i].count_lock);
177 vts[i].driver = &driver; 177 vts[i].driver = &driver;
178 } 178 }
179 console_driver = register_lines(&driver, &console_ops, vts, 179 console_driver = register_lines(&driver, &console_ops, vts,