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>
This commit is contained in:
Родитель
cc4f02486c
Коммит
2116bda6ad
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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" \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче