diff options
author | Richard Weinberger <richard@nod.at> | 2013-03-11 05:05:45 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2013-03-11 05:08:04 -0400 |
commit | 2116bda6ad937d7acb6e2316fd9e65ad6ca01d42 (patch) | |
tree | dc9b20f4bc76b335e8a395b4248f50ac2d3935dc /arch | |
parent | cc4f02486c09977ccbe3ce2276aca5608a44ca00 (diff) |
um: Use tty_port in SIGWINCH handler
The tty below tty_port might get destroyed by the tty layer
while we hold a reference to it.
So we have to carry tty_port around...
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/drivers/chan.h | 2 | ||||
-rw-r--r-- | arch/um/drivers/chan_kern.c | 4 | ||||
-rw-r--r-- | arch/um/drivers/chan_user.c | 12 | ||||
-rw-r--r-- | arch/um/drivers/chan_user.h | 6 | ||||
-rw-r--r-- | arch/um/drivers/line.c | 16 |
5 files changed, 22 insertions, 18 deletions
diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h index 78f1b8999964..c512b0306dd4 100644 --- a/arch/um/drivers/chan.h +++ b/arch/um/drivers/chan.h | |||
@@ -37,7 +37,7 @@ extern int console_write_chan(struct chan *chan, const char *buf, | |||
37 | extern int console_open_chan(struct line *line, struct console *co); | 37 | extern int console_open_chan(struct line *line, struct console *co); |
38 | extern void deactivate_chan(struct chan *chan, int irq); | 38 | extern void deactivate_chan(struct chan *chan, int irq); |
39 | extern void reactivate_chan(struct chan *chan, int irq); | 39 | extern void reactivate_chan(struct chan *chan, int irq); |
40 | extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); | 40 | extern void chan_enable_winch(struct chan *chan, struct tty_port *port); |
41 | extern int enable_chan(struct line *line); | 41 | extern int enable_chan(struct line *line); |
42 | extern void close_chan(struct line *line); | 42 | extern void close_chan(struct line *line); |
43 | extern int chan_window_size(struct line *line, | 43 | extern int chan_window_size(struct line *line, |
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 15c553c239a1..80b47cb71e0a 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -122,10 +122,10 @@ static int open_chan(struct list_head *chans) | |||
122 | return err; | 122 | return err; |
123 | } | 123 | } |
124 | 124 | ||
125 | void chan_enable_winch(struct chan *chan, struct tty_struct *tty) | 125 | void chan_enable_winch(struct chan *chan, struct tty_port *port) |
126 | { | 126 | { |
127 | if (chan && chan->primary && chan->ops->winch) | 127 | if (chan && chan->primary && chan->ops->winch) |
128 | register_winch(chan->fd, tty); | 128 | register_winch(chan->fd, port); |
129 | } | 129 | } |
130 | 130 | ||
131 | static void line_timer_cb(struct work_struct *work) | 131 | static void line_timer_cb(struct work_struct *work) |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 9be670ad23b5..3fd7c3efdb18 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -216,7 +216,7 @@ static int winch_thread(void *arg) | |||
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
219 | static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, | 219 | static int winch_tramp(int fd, struct tty_port *port, int *fd_out, |
220 | unsigned long *stack_out) | 220 | unsigned long *stack_out) |
221 | { | 221 | { |
222 | struct winch_data data; | 222 | struct winch_data data; |
@@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, | |||
271 | return err; | 271 | return err; |
272 | } | 272 | } |
273 | 273 | ||
274 | void register_winch(int fd, struct tty_struct *tty) | 274 | void register_winch(int fd, struct tty_port *port) |
275 | { | 275 | { |
276 | unsigned long stack; | 276 | unsigned long stack; |
277 | int pid, thread, count, thread_fd = -1; | 277 | int pid, thread, count, thread_fd = -1; |
@@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty) | |||
281 | return; | 281 | return; |
282 | 282 | ||
283 | pid = tcgetpgrp(fd); | 283 | pid = tcgetpgrp(fd); |
284 | if (is_skas_winch(pid, fd, tty)) { | 284 | if (is_skas_winch(pid, fd, port)) { |
285 | register_winch_irq(-1, fd, -1, tty, 0); | 285 | register_winch_irq(-1, fd, -1, port, 0); |
286 | return; | 286 | return; |
287 | } | 287 | } |
288 | 288 | ||
289 | if (pid == -1) { | 289 | if (pid == -1) { |
290 | thread = winch_tramp(fd, tty, &thread_fd, &stack); | 290 | thread = winch_tramp(fd, port, &thread_fd, &stack); |
291 | if (thread < 0) | 291 | if (thread < 0) |
292 | return; | 292 | return; |
293 | 293 | ||
294 | register_winch_irq(thread_fd, fd, thread, tty, stack); | 294 | register_winch_irq(thread_fd, fd, thread, port, stack); |
295 | 295 | ||
296 | count = write(thread_fd, &c, sizeof(c)); | 296 | count = write(thread_fd, &c, sizeof(c)); |
297 | if (count != sizeof(c)) | 297 | if (count != sizeof(c)) |
diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h index dc693298eb8f..03f1b565c5f9 100644 --- a/arch/um/drivers/chan_user.h +++ b/arch/um/drivers/chan_user.h | |||
@@ -38,10 +38,10 @@ extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, | |||
38 | unsigned short *cols_out); | 38 | unsigned short *cols_out); |
39 | extern void generic_free(void *data); | 39 | extern void generic_free(void *data); |
40 | 40 | ||
41 | struct tty_struct; | 41 | struct tty_port; |
42 | extern void register_winch(int fd, struct tty_struct *tty); | 42 | extern void register_winch(int fd, struct tty_port *port); |
43 | extern void register_winch_irq(int fd, int tty_fd, int pid, | 43 | extern void register_winch_irq(int fd, int tty_fd, int pid, |
44 | struct tty_struct *tty, unsigned long stack); | 44 | struct tty_port *port, unsigned long stack); |
45 | 45 | ||
46 | #define __channel_help(fn, prefix) \ | 46 | #define __channel_help(fn, prefix) \ |
47 | __uml_help(fn, prefix "[0-9]*=<channel description>\n" \ | 47 | __uml_help(fn, prefix "[0-9]*=<channel description>\n" \ |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 232243aec70c..be541cf69fd2 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -305,7 +305,7 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty) | |||
305 | return ret; | 305 | return ret; |
306 | 306 | ||
307 | if (!line->sigio) { | 307 | if (!line->sigio) { |
308 | chan_enable_winch(line->chan_out, tty); | 308 | chan_enable_winch(line->chan_out, port); |
309 | line->sigio = 1; | 309 | line->sigio = 1; |
310 | } | 310 | } |
311 | 311 | ||
@@ -603,7 +603,7 @@ struct winch { | |||
603 | int fd; | 603 | int fd; |
604 | int tty_fd; | 604 | int tty_fd; |
605 | int pid; | 605 | int pid; |
606 | struct tty_struct *tty; | 606 | struct tty_port *port; |
607 | unsigned long stack; | 607 | unsigned long stack; |
608 | struct work_struct work; | 608 | struct work_struct work; |
609 | }; | 609 | }; |
@@ -657,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
657 | goto out; | 657 | goto out; |
658 | } | 658 | } |
659 | } | 659 | } |
660 | tty = winch->tty; | 660 | tty = tty_port_tty_get(winch->port); |
661 | if (tty != NULL) { | 661 | if (tty != NULL) { |
662 | line = tty->driver_data; | 662 | line = tty->driver_data; |
663 | if (line != NULL) { | 663 | if (line != NULL) { |
@@ -665,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
665 | &tty->winsize.ws_col); | 665 | &tty->winsize.ws_col); |
666 | kill_pgrp(tty->pgrp, SIGWINCH, 1); | 666 | kill_pgrp(tty->pgrp, SIGWINCH, 1); |
667 | } | 667 | } |
668 | tty_kref_put(tty); | ||
668 | } | 669 | } |
669 | out: | 670 | out: |
670 | if (winch->fd != -1) | 671 | if (winch->fd != -1) |
@@ -672,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
672 | return IRQ_HANDLED; | 673 | return IRQ_HANDLED; |
673 | } | 674 | } |
674 | 675 | ||
675 | void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | 676 | void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port, |
676 | unsigned long stack) | 677 | unsigned long stack) |
677 | { | 678 | { |
678 | struct winch *winch; | 679 | struct winch *winch; |
@@ -687,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | |||
687 | .fd = fd, | 688 | .fd = fd, |
688 | .tty_fd = tty_fd, | 689 | .tty_fd = tty_fd, |
689 | .pid = pid, | 690 | .pid = pid, |
690 | .tty = tty, | 691 | .port = port, |
691 | .stack = stack }); | 692 | .stack = stack }); |
692 | 693 | ||
693 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, | 694 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, |
@@ -716,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty) | |||
716 | { | 717 | { |
717 | struct list_head *ele, *next; | 718 | struct list_head *ele, *next; |
718 | struct winch *winch; | 719 | struct winch *winch; |
720 | struct tty_struct *wtty; | ||
719 | 721 | ||
720 | spin_lock(&winch_handler_lock); | 722 | spin_lock(&winch_handler_lock); |
721 | 723 | ||
722 | list_for_each_safe(ele, next, &winch_handlers) { | 724 | list_for_each_safe(ele, next, &winch_handlers) { |
723 | winch = list_entry(ele, struct winch, list); | 725 | winch = list_entry(ele, struct winch, list); |
724 | if (winch->tty == tty) { | 726 | wtty = tty_port_tty_get(winch->port); |
727 | if (wtty == tty) { | ||
725 | free_winch(winch); | 728 | free_winch(winch); |
726 | break; | 729 | break; |
727 | } | 730 | } |
731 | tty_kref_put(wtty); | ||
728 | } | 732 | } |
729 | spin_unlock(&winch_handler_lock); | 733 | spin_unlock(&winch_handler_lock); |
730 | } | 734 | } |