diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 98b126c2ded8..f07637a8f88f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -351,10 +351,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
351 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 351 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
352 | return size; | 352 | return size; |
353 | } | 353 | } |
354 | |||
355 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 354 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
356 | 355 | ||
357 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) | 356 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, |
357 | size_t size) | ||
358 | { | 358 | { |
359 | int copied = 0; | 359 | int copied = 0; |
360 | do { | 360 | do { |
@@ -368,17 +368,16 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s | |||
368 | tb->used += space; | 368 | tb->used += space; |
369 | copied += space; | 369 | copied += space; |
370 | chars += space; | 370 | chars += space; |
371 | /* printk("Flip insert %d.\n", space); */ | ||
372 | } | 371 | } |
373 | /* There is a small chance that we need to split the data over | 372 | /* There is a small chance that we need to split the data over |
374 | several buffers. If this is the case we must loop */ | 373 | several buffers. If this is the case we must loop */ |
375 | while (unlikely(size > copied)); | 374 | while (unlikely(size > copied)); |
376 | return copied; | 375 | return copied; |
377 | } | 376 | } |
378 | |||
379 | EXPORT_SYMBOL(tty_insert_flip_string); | 377 | EXPORT_SYMBOL(tty_insert_flip_string); |
380 | 378 | ||
381 | int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) | 379 | int tty_insert_flip_string_flags(struct tty_struct *tty, |
380 | const unsigned char *chars, const char *flags, size_t size) | ||
382 | { | 381 | { |
383 | int copied = 0; | 382 | int copied = 0; |
384 | do { | 383 | do { |
@@ -399,9 +398,20 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *ch | |||
399 | while (unlikely(size > copied)); | 398 | while (unlikely(size > copied)); |
400 | return copied; | 399 | return copied; |
401 | } | 400 | } |
402 | |||
403 | EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); | 401 | EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); |
404 | 402 | ||
403 | void tty_schedule_flip(struct tty_struct *tty) | ||
404 | { | ||
405 | unsigned long flags; | ||
406 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
407 | if (tty->buf.tail != NULL) { | ||
408 | tty->buf.tail->active = 0; | ||
409 | tty->buf.tail->commit = tty->buf.tail->used; | ||
410 | } | ||
411 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
412 | schedule_delayed_work(&tty->buf.work, 1); | ||
413 | } | ||
414 | EXPORT_SYMBOL(tty_schedule_flip); | ||
405 | 415 | ||
406 | /* | 416 | /* |
407 | * Prepare a block of space in the buffer for data. Returns the length | 417 | * Prepare a block of space in the buffer for data. Returns the length |
@@ -1730,7 +1740,7 @@ static void release_dev(struct file * filp) | |||
1730 | { | 1740 | { |
1731 | struct tty_struct *tty, *o_tty; | 1741 | struct tty_struct *tty, *o_tty; |
1732 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1742 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
1733 | int devpts_master, devpts; | 1743 | int devpts; |
1734 | int idx; | 1744 | int idx; |
1735 | char buf[64]; | 1745 | char buf[64]; |
1736 | unsigned long flags; | 1746 | unsigned long flags; |
@@ -1747,7 +1757,6 @@ static void release_dev(struct file * filp) | |||
1747 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1757 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1748 | tty->driver->subtype == PTY_TYPE_MASTER); | 1758 | tty->driver->subtype == PTY_TYPE_MASTER); |
1749 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; | 1759 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; |
1750 | devpts_master = pty_master && devpts; | ||
1751 | o_tty = tty->link; | 1760 | o_tty = tty->link; |
1752 | 1761 | ||
1753 | #ifdef TTY_PARANOIA_CHECK | 1762 | #ifdef TTY_PARANOIA_CHECK |
@@ -2185,6 +2194,7 @@ static int ptmx_open(struct inode * inode, struct file * filp) | |||
2185 | return 0; | 2194 | return 0; |
2186 | out1: | 2195 | out1: |
2187 | release_dev(filp); | 2196 | release_dev(filp); |
2197 | return retval; | ||
2188 | out: | 2198 | out: |
2189 | down(&allocated_ptys_lock); | 2199 | down(&allocated_ptys_lock); |
2190 | idr_remove(&allocated_ptys, index); | 2200 | idr_remove(&allocated_ptys, index); |
@@ -2713,7 +2723,11 @@ static void __do_SAK(void *arg) | |||
2713 | } | 2723 | } |
2714 | task_lock(p); | 2724 | task_lock(p); |
2715 | if (p->files) { | 2725 | if (p->files) { |
2716 | rcu_read_lock(); | 2726 | /* |
2727 | * We don't take a ref to the file, so we must | ||
2728 | * hold ->file_lock instead. | ||
2729 | */ | ||
2730 | spin_lock(&p->files->file_lock); | ||
2717 | fdt = files_fdtable(p->files); | 2731 | fdt = files_fdtable(p->files); |
2718 | for (i=0; i < fdt->max_fds; i++) { | 2732 | for (i=0; i < fdt->max_fds; i++) { |
2719 | filp = fcheck_files(p->files, i); | 2733 | filp = fcheck_files(p->files, i); |
@@ -2724,11 +2738,11 @@ static void __do_SAK(void *arg) | |||
2724 | printk(KERN_NOTICE "SAK: killed process %d" | 2738 | printk(KERN_NOTICE "SAK: killed process %d" |
2725 | " (%s): fd#%d opened to the tty\n", | 2739 | " (%s): fd#%d opened to the tty\n", |
2726 | p->pid, p->comm, i); | 2740 | p->pid, p->comm, i); |
2727 | send_sig(SIGKILL, p, 1); | 2741 | force_sig(SIGKILL, p); |
2728 | break; | 2742 | break; |
2729 | } | 2743 | } |
2730 | } | 2744 | } |
2731 | rcu_read_unlock(); | 2745 | spin_unlock(&p->files->file_lock); |
2732 | } | 2746 | } |
2733 | task_unlock(p); | 2747 | task_unlock(p); |
2734 | } while_each_thread(g, p); | 2748 | } while_each_thread(g, p); |