diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2007-02-10 04:44:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 13:51:24 -0500 |
commit | 8b6312f4dcc1efe7975731b6c47dd134282bd9ac (patch) | |
tree | 71c94b01bda940c5610d448d0f4a2aa3c7665b4c /drivers/char/tty_io.c | |
parent | 0a7b35cb18c52d651f6ed9cd59edc979200ab880 (diff) |
[PATCH] vt: refactor console SAK processing
This does several things.
- It moves looking up of the current foreground console into process
context where we can safely take the semaphore that protects this
operation.
- It uses the new flavor of work queue processing.
- This generates a factor of do_SAK, __do_SAK that runs immediately.
- This calls __do_SAK with the console semaphore held ensuring nothing
else happens to the console while we process the SAK operation.
- With the console SAK processing moved into process context this
patch removes the xchg operations that I used to attempt to attomically
update struct pid, because of the strange locking used in the SAK processing.
With SAK using the normal console semaphore nothing special is needed.
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 47a6eacb10bc..c57b1f434652 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -3324,10 +3324,8 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
3324 | * Nasty bug: do_SAK is being called in interrupt context. This can | 3324 | * Nasty bug: do_SAK is being called in interrupt context. This can |
3325 | * deadlock. We punt it up to process context. AKPM - 16Mar2001 | 3325 | * deadlock. We punt it up to process context. AKPM - 16Mar2001 |
3326 | */ | 3326 | */ |
3327 | static void __do_SAK(struct work_struct *work) | 3327 | void __do_SAK(struct tty_struct *tty) |
3328 | { | 3328 | { |
3329 | struct tty_struct *tty = | ||
3330 | container_of(work, struct tty_struct, SAK_work); | ||
3331 | #ifdef TTY_SOFT_SAK | 3329 | #ifdef TTY_SOFT_SAK |
3332 | tty_hangup(tty); | 3330 | tty_hangup(tty); |
3333 | #else | 3331 | #else |
@@ -3394,6 +3392,13 @@ static void __do_SAK(struct work_struct *work) | |||
3394 | #endif | 3392 | #endif |
3395 | } | 3393 | } |
3396 | 3394 | ||
3395 | static void do_SAK_work(struct work_struct *work) | ||
3396 | { | ||
3397 | struct tty_struct *tty = | ||
3398 | container_of(work, struct tty_struct, SAK_work); | ||
3399 | __do_SAK(tty); | ||
3400 | } | ||
3401 | |||
3397 | /* | 3402 | /* |
3398 | * The tq handling here is a little racy - tty->SAK_work may already be queued. | 3403 | * The tq handling here is a little racy - tty->SAK_work may already be queued. |
3399 | * Fortunately we don't need to worry, because if ->SAK_work is already queued, | 3404 | * Fortunately we don't need to worry, because if ->SAK_work is already queued, |
@@ -3404,7 +3409,7 @@ void do_SAK(struct tty_struct *tty) | |||
3404 | { | 3409 | { |
3405 | if (!tty) | 3410 | if (!tty) |
3406 | return; | 3411 | return; |
3407 | PREPARE_WORK(&tty->SAK_work, __do_SAK); | 3412 | PREPARE_WORK(&tty->SAK_work, do_SAK_work); |
3408 | schedule_work(&tty->SAK_work); | 3413 | schedule_work(&tty->SAK_work); |
3409 | } | 3414 | } |
3410 | 3415 | ||