aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-07-16 02:38:55 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:38 -0400
commit42a359e31a0e438b5b978a8f0fecdbd3c86bb033 (patch)
treefc6a6a11e1187e163ba694bf4ab5cf48aa528f34 /arch/um/drivers/line.c
parentd14ad81f800a57d3f21f8e98556c728968883e9a (diff)
uml: SIGIO support cleanup
Cleanup of the SIGWINCH support. Some code and comment reformatting. The stack used for SIGWINCH threads was leaked. This is now fixed by storing it with the pid and other information, and freeing it when the thread is killed. If something goes wrong with a WIGWINCH thread, and this is discovered in the interrupt handler, the winch record would leak. It is now freed, except that the IRQ isn't freed. This is hard to do from interrupt context. This has the side-effect that the IRQ system maintains a reference to the freed structure, but that shouldn't cause a problem since the descriptor is disabled. register_winch_irq is now much better about cleaning up after an initialization failure. Signed-off-by: Jeff Dike <jdike@linux.intel.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.c60
1 files changed, 39 insertions, 21 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 1fb3e51108b9..3e0b68e297f2 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -749,8 +749,24 @@ struct winch {
749 int tty_fd; 749 int tty_fd;
750 int pid; 750 int pid;
751 struct tty_struct *tty; 751 struct tty_struct *tty;
752 unsigned long stack;
752}; 753};
753 754
755static void free_winch(struct winch *winch, int free_irq_ok)
756{
757 list_del(&winch->list);
758
759 if (winch->pid != -1)
760 os_kill_process(winch->pid, 1);
761 if (winch->fd != -1)
762 os_close_file(winch->fd);
763 if (winch->stack != 0)
764 free_stack(winch->stack, 0);
765 if (free_irq_ok)
766 free_irq(WINCH_IRQ, winch);
767 kfree(winch);
768}
769
754static irqreturn_t winch_interrupt(int irq, void *data) 770static irqreturn_t winch_interrupt(int irq, void *data)
755{ 771{
756 struct winch *winch = data; 772 struct winch *winch = data;
@@ -767,12 +783,13 @@ static irqreturn_t winch_interrupt(int irq, void *data)
767 "errno = %d\n", -err); 783 "errno = %d\n", -err);
768 printk("fd %d is losing SIGWINCH support\n", 784 printk("fd %d is losing SIGWINCH support\n",
769 winch->tty_fd); 785 winch->tty_fd);
786 free_winch(winch, 0);
770 return IRQ_HANDLED; 787 return IRQ_HANDLED;
771 } 788 }
772 goto out; 789 goto out;
773 } 790 }
774 } 791 }
775 tty = winch->tty; 792 tty = winch->tty;
776 if (tty != NULL) { 793 if (tty != NULL) {
777 line = tty->driver_data; 794 line = tty->driver_data;
778 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 795 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
@@ -785,43 +802,44 @@ static irqreturn_t winch_interrupt(int irq, void *data)
785 return IRQ_HANDLED; 802 return IRQ_HANDLED;
786} 803}
787 804
788void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) 805void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
806 unsigned long stack)
789{ 807{
790 struct winch *winch; 808 struct winch *winch;
791 809
792 winch = kmalloc(sizeof(*winch), GFP_KERNEL); 810 winch = kmalloc(sizeof(*winch), GFP_KERNEL);
793 if (winch == NULL) { 811 if (winch == NULL) {
794 printk("register_winch_irq - kmalloc failed\n"); 812 printk("register_winch_irq - kmalloc failed\n");
795 return; 813 goto cleanup;
796 } 814 }
797 815
798 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), 816 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
799 .fd = fd, 817 .fd = fd,
800 .tty_fd = tty_fd, 818 .tty_fd = tty_fd,
801 .pid = pid, 819 .pid = pid,
802 .tty = tty }); 820 .tty = tty,
821 .stack = stack });
822
823 if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
824 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
825 "winch", winch) < 0) {
826 printk("register_winch_irq - failed to register IRQ\n");
827 goto out_free;
828 }
803 829
804 spin_lock(&winch_handler_lock); 830 spin_lock(&winch_handler_lock);
805 list_add(&winch->list, &winch_handlers); 831 list_add(&winch->list, &winch_handlers);
806 spin_unlock(&winch_handler_lock); 832 spin_unlock(&winch_handler_lock);
807 833
808 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 834 return;
809 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
810 "winch", winch) < 0)
811 printk("register_winch_irq - failed to register IRQ\n");
812}
813
814static void free_winch(struct winch *winch)
815{
816 list_del(&winch->list);
817
818 if(winch->pid != -1)
819 os_kill_process(winch->pid, 1);
820 if(winch->fd != -1)
821 os_close_file(winch->fd);
822 835
823 free_irq(WINCH_IRQ, winch); 836 out_free:
824 kfree(winch); 837 kfree(winch);
838 cleanup:
839 os_kill_process(pid, 1);
840 os_close_file(fd);
841 if (stack != 0)
842 free_stack(stack, 0);
825} 843}
826 844
827static void unregister_winch(struct tty_struct *tty) 845static void unregister_winch(struct tty_struct *tty)
@@ -834,7 +852,7 @@ static void unregister_winch(struct tty_struct *tty)
834 list_for_each(ele, &winch_handlers){ 852 list_for_each(ele, &winch_handlers){
835 winch = list_entry(ele, struct winch, list); 853 winch = list_entry(ele, struct winch, list);
836 if(winch->tty == tty){ 854 if(winch->tty == tty){
837 free_winch(winch); 855 free_winch(winch, 1);
838 break; 856 break;
839 } 857 }
840 } 858 }
@@ -850,7 +868,7 @@ static void winch_cleanup(void)
850 868
851 list_for_each_safe(ele, next, &winch_handlers){ 869 list_for_each_safe(ele, next, &winch_handlers){
852 winch = list_entry(ele, struct winch, list); 870 winch = list_entry(ele, struct winch, list);
853 free_winch(winch); 871 free_winch(winch, 1);
854 } 872 }
855 873
856 spin_unlock(&winch_handler_lock); 874 spin_unlock(&winch_handler_lock);