diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-05-14 11:11:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-15 13:19:30 -0400 |
| commit | 487ad7efbf6b0ec338cdfc2a7b0fbeb53f17a94c (patch) | |
| tree | e2bc37cc97680403bf664a5944b10cdd907b9f10 | |
| parent | 8568dae21e186fbb111bbe6583033a33fe26f83d (diff) | |
tty: fix BKL related leak and crash
Enabling the BKL to be lockdep tracked uncovered the following
upstream kernel bug in the tty code, which caused a BKL
reference leak:
================================================
[ BUG: lock held when returning to user space! ]
------------------------------------------------
dmesg/3121 is leaving the kernel with locks still held!
1 lock held by dmesg/3121:
#0: (kernel_mutex){--..}, at: [<c02f34d9>] opost+0x24/0x194
this might explain some of the atomicity warnings and crashes
that -tip tree testing has been experiencing since the BKL
was converted back to a spinlock.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/char/n_tty.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 19105ec203f7..8096389b0dc2 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
| @@ -282,16 +282,20 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
| 282 | if (O_ONLRET(tty)) | 282 | if (O_ONLRET(tty)) |
| 283 | tty->column = 0; | 283 | tty->column = 0; |
| 284 | if (O_ONLCR(tty)) { | 284 | if (O_ONLCR(tty)) { |
| 285 | if (space < 2) | 285 | if (space < 2) { |
| 286 | unlock_kernel(); | ||
| 286 | return -1; | 287 | return -1; |
| 288 | } | ||
| 287 | tty_put_char(tty, '\r'); | 289 | tty_put_char(tty, '\r'); |
| 288 | tty->column = 0; | 290 | tty->column = 0; |
| 289 | } | 291 | } |
| 290 | tty->canon_column = tty->column; | 292 | tty->canon_column = tty->column; |
| 291 | break; | 293 | break; |
| 292 | case '\r': | 294 | case '\r': |
| 293 | if (O_ONOCR(tty) && tty->column == 0) | 295 | if (O_ONOCR(tty) && tty->column == 0) { |
| 296 | unlock_kernel(); | ||
| 294 | return 0; | 297 | return 0; |
| 298 | } | ||
| 295 | if (O_OCRNL(tty)) { | 299 | if (O_OCRNL(tty)) { |
| 296 | c = '\n'; | 300 | c = '\n'; |
| 297 | if (O_ONLRET(tty)) | 301 | if (O_ONLRET(tty)) |
| @@ -303,10 +307,13 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
| 303 | case '\t': | 307 | case '\t': |
| 304 | spaces = 8 - (tty->column & 7); | 308 | spaces = 8 - (tty->column & 7); |
| 305 | if (O_TABDLY(tty) == XTABS) { | 309 | if (O_TABDLY(tty) == XTABS) { |
| 306 | if (space < spaces) | 310 | if (space < spaces) { |
| 311 | unlock_kernel(); | ||
| 307 | return -1; | 312 | return -1; |
| 313 | } | ||
| 308 | tty->column += spaces; | 314 | tty->column += spaces; |
| 309 | tty->ops->write(tty, " ", spaces); | 315 | tty->ops->write(tty, " ", spaces); |
| 316 | unlock_kernel(); | ||
| 310 | return 0; | 317 | return 0; |
| 311 | } | 318 | } |
| 312 | tty->column += spaces; | 319 | tty->column += spaces; |
