diff options
| author | Richard Weinberger <richard@nod.at> | 2013-03-11 10:05:45 +0100 | 
|---|---|---|
| committer | Richard Weinberger <richard@nod.at> | 2013-03-11 10:08:04 +0100 | 
| commit | 2116bda6ad937d7acb6e2316fd9e65ad6ca01d42 (patch) | |
| tree | dc9b20f4bc76b335e8a395b4248f50ac2d3935dc | |
| parent | cc4f02486c09977ccbe3ce2276aca5608a44ca00 (diff) | |
| download | olio-linux-3.10-2116bda6ad937d7acb6e2316fd9e65ad6ca01d42.tar.xz olio-linux-3.10-2116bda6ad937d7acb6e2316fd9e65ad6ca01d42.zip  | |
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>
| -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 78f1b899996..c512b0306dd 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,  extern int console_open_chan(struct line *line, struct console *co);  extern void deactivate_chan(struct chan *chan, int irq);  extern void reactivate_chan(struct chan *chan, int irq); -extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); +extern void chan_enable_winch(struct chan *chan, struct tty_port *port);  extern int enable_chan(struct line *line);  extern void close_chan(struct line *line);  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 15c553c239a..80b47cb71e0 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)  	return err;  } -void chan_enable_winch(struct chan *chan, struct tty_struct *tty) +void chan_enable_winch(struct chan *chan, struct tty_port *port)  {  	if (chan && chan->primary && chan->ops->winch) -		register_winch(chan->fd, tty); +		register_winch(chan->fd, port);  }  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 9be670ad23b..3fd7c3efdb1 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)  	}  } -static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, +static int winch_tramp(int fd, struct tty_port *port, int *fd_out,  		       unsigned long *stack_out)  {  	struct winch_data data; @@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,  	return err;  } -void register_winch(int fd, struct tty_struct *tty) +void register_winch(int fd, struct tty_port *port)  {  	unsigned long stack;  	int pid, thread, count, thread_fd = -1; @@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty)  		return;  	pid = tcgetpgrp(fd); -	if (is_skas_winch(pid, fd, tty)) { -		register_winch_irq(-1, fd, -1, tty, 0); +	if (is_skas_winch(pid, fd, port)) { +		register_winch_irq(-1, fd, -1, port, 0);  		return;  	}  	if (pid == -1) { -		thread = winch_tramp(fd, tty, &thread_fd, &stack); +		thread = winch_tramp(fd, port, &thread_fd, &stack);  		if (thread < 0)  			return; -		register_winch_irq(thread_fd, fd, thread, tty, stack); +		register_winch_irq(thread_fd, fd, thread, port, stack);  		count = write(thread_fd, &c, sizeof(c));  		if (count != sizeof(c)) diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h index dc693298eb8..03f1b565c5f 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,  			       unsigned short *cols_out);  extern void generic_free(void *data); -struct tty_struct; -extern void register_winch(int fd,  struct tty_struct *tty); +struct tty_port; +extern void register_winch(int fd,  struct tty_port *port);  extern void register_winch_irq(int fd, int tty_fd, int pid, -			       struct tty_struct *tty, unsigned long stack); +			       struct tty_port *port, unsigned long stack);  #define __channel_help(fn, prefix) \  __uml_help(fn, prefix "[0-9]*=<channel description>\n" \ diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 232243aec70..be541cf69fd 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)  		return ret;  	if (!line->sigio) { -		chan_enable_winch(line->chan_out, tty); +		chan_enable_winch(line->chan_out, port);  		line->sigio = 1;  	} @@ -603,7 +603,7 @@ struct winch {  	int fd;  	int tty_fd;  	int pid; -	struct tty_struct *tty; +	struct tty_port *port;  	unsigned long stack;  	struct work_struct work;  }; @@ -657,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)  			goto out;  		}  	} -	tty = winch->tty; +	tty = tty_port_tty_get(winch->port);  	if (tty != NULL) {  		line = tty->driver_data;  		if (line != NULL) { @@ -665,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)  					 &tty->winsize.ws_col);  			kill_pgrp(tty->pgrp, SIGWINCH, 1);  		} +		tty_kref_put(tty);  	}   out:  	if (winch->fd != -1) @@ -672,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)  	return IRQ_HANDLED;  } -void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, +void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,  			unsigned long stack)  {  	struct winch *winch; @@ -687,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,  				   .fd  	= fd,  				   .tty_fd 	= tty_fd,  				   .pid  	= pid, -				   .tty 	= tty, +				   .port 	= port,  				   .stack	= stack });  	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, @@ -716,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty)  {  	struct list_head *ele, *next;  	struct winch *winch; +	struct tty_struct *wtty;  	spin_lock(&winch_handler_lock);  	list_for_each_safe(ele, next, &winch_handlers) {  		winch = list_entry(ele, struct winch, list); -		if (winch->tty == tty) { +		wtty = tty_port_tty_get(winch->port); +		if (wtty == tty) {  			free_winch(winch);  			break;  		} +		tty_kref_put(wtty);  	}  	spin_unlock(&winch_handler_lock);  }  |