diff options
-rw-r--r-- | drivers/tty/amiserial.c | 14 | ||||
-rw-r--r-- | drivers/tty/cyclades.c | 2 | ||||
-rw-r--r-- | drivers/tty/n_r3964.c | 10 | ||||
-rw-r--r-- | drivers/tty/pty.c | 25 | ||||
-rw-r--r-- | drivers/tty/serial/crisv10.c | 8 | ||||
-rw-r--r-- | drivers/tty/synclink.c | 4 | ||||
-rw-r--r-- | drivers/tty/synclink_gt.c | 4 | ||||
-rw-r--r-- | drivers/tty/synclinkmp.c | 4 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 66 | ||||
-rw-r--r-- | drivers/tty/tty_ldisc.c | 69 | ||||
-rw-r--r-- | drivers/tty/tty_mutex.c | 71 | ||||
-rw-r--r-- | drivers/tty/tty_port.c | 6 | ||||
-rw-r--r-- | include/linux/tty.h | 23 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 4 |
14 files changed, 190 insertions, 120 deletions
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 0e8441e73ee0..998731f01d62 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c | |||
@@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, | |||
1033 | if (!retinfo) | 1033 | if (!retinfo) |
1034 | return -EFAULT; | 1034 | return -EFAULT; |
1035 | memset(&tmp, 0, sizeof(tmp)); | 1035 | memset(&tmp, 0, sizeof(tmp)); |
1036 | tty_lock(); | 1036 | tty_lock(tty); |
1037 | tmp.line = tty->index; | 1037 | tmp.line = tty->index; |
1038 | tmp.port = state->port; | 1038 | tmp.port = state->port; |
1039 | tmp.flags = state->tport.flags; | 1039 | tmp.flags = state->tport.flags; |
@@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, | |||
1042 | tmp.close_delay = state->tport.close_delay; | 1042 | tmp.close_delay = state->tport.close_delay; |
1043 | tmp.closing_wait = state->tport.closing_wait; | 1043 | tmp.closing_wait = state->tport.closing_wait; |
1044 | tmp.custom_divisor = state->custom_divisor; | 1044 | tmp.custom_divisor = state->custom_divisor; |
1045 | tty_unlock(); | 1045 | tty_unlock(tty); |
1046 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) | 1046 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) |
1047 | return -EFAULT; | 1047 | return -EFAULT; |
1048 | return 0; | 1048 | return 0; |
@@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, | |||
1059 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | 1059 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) |
1060 | return -EFAULT; | 1060 | return -EFAULT; |
1061 | 1061 | ||
1062 | tty_lock(); | 1062 | tty_lock(tty); |
1063 | change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || | 1063 | change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || |
1064 | new_serial.custom_divisor != state->custom_divisor; | 1064 | new_serial.custom_divisor != state->custom_divisor; |
1065 | if (new_serial.irq || new_serial.port != state->port || | 1065 | if (new_serial.irq || new_serial.port != state->port || |
1066 | new_serial.xmit_fifo_size != state->xmit_fifo_size) { | 1066 | new_serial.xmit_fifo_size != state->xmit_fifo_size) { |
1067 | tty_unlock(); | 1067 | tty_unlock(tty); |
1068 | return -EINVAL; | 1068 | return -EINVAL; |
1069 | } | 1069 | } |
1070 | 1070 | ||
@@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, | |||
1074 | (new_serial.xmit_fifo_size != state->xmit_fifo_size) || | 1074 | (new_serial.xmit_fifo_size != state->xmit_fifo_size) || |
1075 | ((new_serial.flags & ~ASYNC_USR_MASK) != | 1075 | ((new_serial.flags & ~ASYNC_USR_MASK) != |
1076 | (port->flags & ~ASYNC_USR_MASK))) { | 1076 | (port->flags & ~ASYNC_USR_MASK))) { |
1077 | tty_unlock(); | 1077 | tty_unlock(tty); |
1078 | return -EPERM; | 1078 | return -EPERM; |
1079 | } | 1079 | } |
1080 | port->flags = ((port->flags & ~ASYNC_USR_MASK) | | 1080 | port->flags = ((port->flags & ~ASYNC_USR_MASK) | |
@@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, | |||
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | if (new_serial.baud_base < 9600) { | 1086 | if (new_serial.baud_base < 9600) { |
1087 | tty_unlock(); | 1087 | tty_unlock(tty); |
1088 | return -EINVAL; | 1088 | return -EINVAL; |
1089 | } | 1089 | } |
1090 | 1090 | ||
@@ -1116,7 +1116,7 @@ check_and_exit: | |||
1116 | } | 1116 | } |
1117 | } else | 1117 | } else |
1118 | retval = startup(tty, state); | 1118 | retval = startup(tty, state); |
1119 | tty_unlock(); | 1119 | tty_unlock(tty); |
1120 | return retval; | 1120 | return retval; |
1121 | } | 1121 | } |
1122 | 1122 | ||
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index e77db714ab26..c8850ea832af 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c | |||
@@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
1599 | * If the port is the middle of closing, bail out now | 1599 | * If the port is the middle of closing, bail out now |
1600 | */ | 1600 | */ |
1601 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | 1601 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { |
1602 | wait_event_interruptible_tty(info->port.close_wait, | 1602 | wait_event_interruptible_tty(tty, info->port.close_wait, |
1603 | !(info->port.flags & ASYNC_CLOSING)); | 1603 | !(info->port.flags & ASYNC_CLOSING)); |
1604 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 1604 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
1605 | } | 1605 | } |
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 5c6c31459a2f..1e6405070ce6 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c | |||
@@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1065 | 1065 | ||
1066 | TRACE_L("read()"); | 1066 | TRACE_L("read()"); |
1067 | 1067 | ||
1068 | tty_lock(); | 1068 | tty_lock(tty); |
1069 | 1069 | ||
1070 | pClient = findClient(pInfo, task_pid(current)); | 1070 | pClient = findClient(pInfo, task_pid(current)); |
1071 | if (pClient) { | 1071 | if (pClient) { |
@@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1077 | goto unlock; | 1077 | goto unlock; |
1078 | } | 1078 | } |
1079 | /* block until there is a message: */ | 1079 | /* block until there is a message: */ |
1080 | wait_event_interruptible_tty(pInfo->read_wait, | 1080 | wait_event_interruptible_tty(tty, pInfo->read_wait, |
1081 | (pMsg = remove_msg(pInfo, pClient))); | 1081 | (pMsg = remove_msg(pInfo, pClient))); |
1082 | } | 1082 | } |
1083 | 1083 | ||
@@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1107 | } | 1107 | } |
1108 | ret = -EPERM; | 1108 | ret = -EPERM; |
1109 | unlock: | 1109 | unlock: |
1110 | tty_unlock(); | 1110 | tty_unlock(tty); |
1111 | return ret; | 1111 | return ret; |
1112 | } | 1112 | } |
1113 | 1113 | ||
@@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1156 | pHeader->locks = 0; | 1156 | pHeader->locks = 0; |
1157 | pHeader->owner = NULL; | 1157 | pHeader->owner = NULL; |
1158 | 1158 | ||
1159 | tty_lock(); | 1159 | tty_lock(tty); |
1160 | 1160 | ||
1161 | pClient = findClient(pInfo, task_pid(current)); | 1161 | pClient = findClient(pInfo, task_pid(current)); |
1162 | if (pClient) { | 1162 | if (pClient) { |
@@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1175 | add_tx_queue(pInfo, pHeader); | 1175 | add_tx_queue(pInfo, pHeader); |
1176 | trigger_transmit(pInfo); | 1176 | trigger_transmit(pInfo); |
1177 | 1177 | ||
1178 | tty_unlock(); | 1178 | tty_unlock(tty); |
1179 | 1179 | ||
1180 | return 0; | 1180 | return 0; |
1181 | } | 1181 | } |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index d6579a9064c4..4399f1dbd131 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
47 | wake_up_interruptible(&tty->read_wait); | 47 | wake_up_interruptible(&tty->read_wait); |
48 | wake_up_interruptible(&tty->write_wait); | 48 | wake_up_interruptible(&tty->write_wait); |
49 | tty->packet = 0; | 49 | tty->packet = 0; |
50 | /* Review - krefs on tty_link ?? */ | ||
50 | if (!tty->link) | 51 | if (!tty->link) |
51 | return; | 52 | return; |
52 | tty->link->packet = 0; | 53 | tty->link->packet = 0; |
@@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
62 | mutex_unlock(&devpts_mutex); | 63 | mutex_unlock(&devpts_mutex); |
63 | } | 64 | } |
64 | #endif | 65 | #endif |
65 | tty_unlock(); | 66 | tty_unlock(tty); |
66 | tty_vhangup(tty->link); | 67 | tty_vhangup(tty->link); |
67 | tty_lock(); | 68 | tty_lock(tty); |
68 | } | 69 | } |
69 | } | 70 | } |
70 | 71 | ||
@@ -617,26 +618,27 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
617 | return retval; | 618 | return retval; |
618 | 619 | ||
619 | /* find a device that is not in use. */ | 620 | /* find a device that is not in use. */ |
620 | tty_lock(); | 621 | mutex_lock(&devpts_mutex); |
621 | index = devpts_new_index(inode); | 622 | index = devpts_new_index(inode); |
622 | tty_unlock(); | ||
623 | if (index < 0) { | 623 | if (index < 0) { |
624 | retval = index; | 624 | retval = index; |
625 | goto err_file; | 625 | goto err_file; |
626 | } | 626 | } |
627 | 627 | ||
628 | mutex_unlock(&devpts_mutex); | ||
629 | |||
628 | mutex_lock(&tty_mutex); | 630 | mutex_lock(&tty_mutex); |
629 | mutex_lock(&devpts_mutex); | ||
630 | tty = tty_init_dev(ptm_driver, index); | 631 | tty = tty_init_dev(ptm_driver, index); |
631 | mutex_unlock(&devpts_mutex); | ||
632 | tty_lock(); | ||
633 | mutex_unlock(&tty_mutex); | ||
634 | 632 | ||
635 | if (IS_ERR(tty)) { | 633 | if (IS_ERR(tty)) { |
636 | retval = PTR_ERR(tty); | 634 | retval = PTR_ERR(tty); |
637 | goto out; | 635 | goto out; |
638 | } | 636 | } |
639 | 637 | ||
638 | /* The tty returned here is locked so we can safely | ||
639 | drop the mutex */ | ||
640 | mutex_unlock(&tty_mutex); | ||
641 | |||
640 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 642 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
641 | 643 | ||
642 | tty_add_file(tty, filp); | 644 | tty_add_file(tty, filp); |
@@ -649,16 +651,17 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
649 | if (retval) | 651 | if (retval) |
650 | goto err_release; | 652 | goto err_release; |
651 | 653 | ||
652 | tty_unlock(); | 654 | tty_unlock(tty); |
653 | return 0; | 655 | return 0; |
654 | err_release: | 656 | err_release: |
655 | tty_unlock(); | 657 | tty_unlock(tty); |
656 | tty_release(inode, filp); | 658 | tty_release(inode, filp); |
657 | return retval; | 659 | return retval; |
658 | out: | 660 | out: |
661 | mutex_unlock(&tty_mutex); | ||
659 | devpts_kill_index(inode, index); | 662 | devpts_kill_index(inode, index); |
660 | tty_unlock(); | ||
661 | err_file: | 663 | err_file: |
664 | mutex_unlock(&devpts_mutex); | ||
662 | tty_free_file(filp); | 665 | tty_free_file(filp); |
663 | return retval; | 666 | return retval; |
664 | } | 667 | } |
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 6b705b243522..a770b1012962 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c | |||
@@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3976 | */ | 3976 | */ |
3977 | if (tty_hung_up_p(filp) || | 3977 | if (tty_hung_up_p(filp) || |
3978 | (info->flags & ASYNC_CLOSING)) { | 3978 | (info->flags & ASYNC_CLOSING)) { |
3979 | wait_event_interruptible_tty(info->close_wait, | 3979 | wait_event_interruptible_tty(tty, info->close_wait, |
3980 | !(info->flags & ASYNC_CLOSING)); | 3980 | !(info->flags & ASYNC_CLOSING)); |
3981 | #ifdef SERIAL_DO_RESTART | 3981 | #ifdef SERIAL_DO_RESTART |
3982 | if (info->flags & ASYNC_HUP_NOTIFY) | 3982 | if (info->flags & ASYNC_HUP_NOTIFY) |
@@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
4052 | printk("block_til_ready blocking: ttyS%d, count = %d\n", | 4052 | printk("block_til_ready blocking: ttyS%d, count = %d\n", |
4053 | info->line, info->count); | 4053 | info->line, info->count); |
4054 | #endif | 4054 | #endif |
4055 | tty_unlock(); | 4055 | tty_unlock(tty); |
4056 | schedule(); | 4056 | schedule(); |
4057 | tty_lock(); | 4057 | tty_lock(tty); |
4058 | } | 4058 | } |
4059 | set_current_state(TASK_RUNNING); | 4059 | set_current_state(TASK_RUNNING); |
4060 | remove_wait_queue(&info->open_wait, &wait); | 4060 | remove_wait_queue(&info->open_wait, &wait); |
@@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4115 | */ | 4115 | */ |
4116 | if (tty_hung_up_p(filp) || | 4116 | if (tty_hung_up_p(filp) || |
4117 | (info->flags & ASYNC_CLOSING)) { | 4117 | (info->flags & ASYNC_CLOSING)) { |
4118 | wait_event_interruptible_tty(info->close_wait, | 4118 | wait_event_interruptible_tty(tty, info->close_wait, |
4119 | !(info->flags & ASYNC_CLOSING)); | 4119 | !(info->flags & ASYNC_CLOSING)); |
4120 | #ifdef SERIAL_DO_RESTART | 4120 | #ifdef SERIAL_DO_RESTART |
4121 | return ((info->flags & ASYNC_HUP_NOTIFY) ? | 4121 | return ((info->flags & ASYNC_HUP_NOTIFY) ? |
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index bdeeb3133f62..991bae821232 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c | |||
@@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3338 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | 3338 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", |
3339 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3339 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3340 | 3340 | ||
3341 | tty_unlock(); | 3341 | tty_unlock(tty); |
3342 | schedule(); | 3342 | schedule(); |
3343 | tty_lock(); | 3343 | tty_lock(tty); |
3344 | } | 3344 | } |
3345 | 3345 | ||
3346 | set_current_state(TASK_RUNNING); | 3346 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index f02d18a391e5..913025369fe7 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c | |||
@@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3336 | } | 3336 | } |
3337 | 3337 | ||
3338 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); | 3338 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); |
3339 | tty_unlock(); | 3339 | tty_unlock(tty); |
3340 | schedule(); | 3340 | schedule(); |
3341 | tty_lock(); | 3341 | tty_lock(tty); |
3342 | } | 3342 | } |
3343 | 3343 | ||
3344 | set_current_state(TASK_RUNNING); | 3344 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index ae75a3c21fd3..95fd4e20b963 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c | |||
@@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3357 | printk("%s(%d):%s block_til_ready() count=%d\n", | 3357 | printk("%s(%d):%s block_til_ready() count=%d\n", |
3358 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3358 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3359 | 3359 | ||
3360 | tty_unlock(); | 3360 | tty_unlock(tty); |
3361 | schedule(); | 3361 | schedule(); |
3362 | tty_lock(); | 3362 | tty_lock(tty); |
3363 | } | 3363 | } |
3364 | 3364 | ||
3365 | set_current_state(TASK_RUNNING); | 3365 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6784aae210e3..690224483fab 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -187,6 +187,7 @@ void free_tty_struct(struct tty_struct *tty) | |||
187 | put_device(tty->dev); | 187 | put_device(tty->dev); |
188 | kfree(tty->write_buf); | 188 | kfree(tty->write_buf); |
189 | tty_buffer_free_all(tty); | 189 | tty_buffer_free_all(tty); |
190 | tty->magic = 0xDEADDEAD; | ||
190 | kfree(tty); | 191 | kfree(tty); |
191 | } | 192 | } |
192 | 193 | ||
@@ -575,7 +576,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
575 | } | 576 | } |
576 | spin_unlock(&redirect_lock); | 577 | spin_unlock(&redirect_lock); |
577 | 578 | ||
578 | tty_lock(); | 579 | tty_lock(tty); |
579 | 580 | ||
580 | /* some functions below drop BTM, so we need this bit */ | 581 | /* some functions below drop BTM, so we need this bit */ |
581 | set_bit(TTY_HUPPING, &tty->flags); | 582 | set_bit(TTY_HUPPING, &tty->flags); |
@@ -668,7 +669,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
668 | clear_bit(TTY_HUPPING, &tty->flags); | 669 | clear_bit(TTY_HUPPING, &tty->flags); |
669 | tty_ldisc_enable(tty); | 670 | tty_ldisc_enable(tty); |
670 | 671 | ||
671 | tty_unlock(); | 672 | tty_unlock(tty); |
672 | 673 | ||
673 | if (f) | 674 | if (f) |
674 | fput(f); | 675 | fput(f); |
@@ -1105,12 +1106,12 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
1105 | { | 1106 | { |
1106 | if (tty) { | 1107 | if (tty) { |
1107 | mutex_lock(&tty->atomic_write_lock); | 1108 | mutex_lock(&tty->atomic_write_lock); |
1108 | tty_lock(); | 1109 | tty_lock(tty); |
1109 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | 1110 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { |
1110 | tty_unlock(); | 1111 | tty_unlock(tty); |
1111 | tty->ops->write(tty, msg, strlen(msg)); | 1112 | tty->ops->write(tty, msg, strlen(msg)); |
1112 | } else | 1113 | } else |
1113 | tty_unlock(); | 1114 | tty_unlock(tty); |
1114 | tty_write_unlock(tty); | 1115 | tty_write_unlock(tty); |
1115 | } | 1116 | } |
1116 | return; | 1117 | return; |
@@ -1403,6 +1404,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) | |||
1403 | } | 1404 | } |
1404 | initialize_tty_struct(tty, driver, idx); | 1405 | initialize_tty_struct(tty, driver, idx); |
1405 | 1406 | ||
1407 | tty_lock(tty); | ||
1406 | retval = tty_driver_install_tty(driver, tty); | 1408 | retval = tty_driver_install_tty(driver, tty); |
1407 | if (retval < 0) | 1409 | if (retval < 0) |
1408 | goto err_deinit_tty; | 1410 | goto err_deinit_tty; |
@@ -1418,9 +1420,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) | |||
1418 | retval = tty_ldisc_setup(tty, tty->link); | 1420 | retval = tty_ldisc_setup(tty, tty->link); |
1419 | if (retval) | 1421 | if (retval) |
1420 | goto err_release_tty; | 1422 | goto err_release_tty; |
1423 | /* Return the tty locked so that it cannot vanish under the caller */ | ||
1421 | return tty; | 1424 | return tty; |
1422 | 1425 | ||
1423 | err_deinit_tty: | 1426 | err_deinit_tty: |
1427 | tty_unlock(tty); | ||
1424 | deinitialize_tty_struct(tty); | 1428 | deinitialize_tty_struct(tty); |
1425 | free_tty_struct(tty); | 1429 | free_tty_struct(tty); |
1426 | err_module_put: | 1430 | err_module_put: |
@@ -1429,6 +1433,7 @@ err_module_put: | |||
1429 | 1433 | ||
1430 | /* call the tty release_tty routine to clean out this slot */ | 1434 | /* call the tty release_tty routine to clean out this slot */ |
1431 | err_release_tty: | 1435 | err_release_tty: |
1436 | tty_unlock(tty); | ||
1432 | printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " | 1437 | printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " |
1433 | "clearing slot %d\n", idx); | 1438 | "clearing slot %d\n", idx); |
1434 | release_tty(tty, idx); | 1439 | release_tty(tty, idx); |
@@ -1622,7 +1627,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1622 | if (tty_paranoia_check(tty, inode, __func__)) | 1627 | if (tty_paranoia_check(tty, inode, __func__)) |
1623 | return 0; | 1628 | return 0; |
1624 | 1629 | ||
1625 | tty_lock(); | 1630 | tty_lock(tty); |
1626 | check_tty_count(tty, __func__); | 1631 | check_tty_count(tty, __func__); |
1627 | 1632 | ||
1628 | __tty_fasync(-1, filp, 0); | 1633 | __tty_fasync(-1, filp, 0); |
@@ -1631,10 +1636,11 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1631 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1636 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1632 | tty->driver->subtype == PTY_TYPE_MASTER); | 1637 | tty->driver->subtype == PTY_TYPE_MASTER); |
1633 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; | 1638 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; |
1639 | /* Review: parallel close */ | ||
1634 | o_tty = tty->link; | 1640 | o_tty = tty->link; |
1635 | 1641 | ||
1636 | if (tty_release_checks(tty, o_tty, idx)) { | 1642 | if (tty_release_checks(tty, o_tty, idx)) { |
1637 | tty_unlock(); | 1643 | tty_unlock(tty); |
1638 | return 0; | 1644 | return 0; |
1639 | } | 1645 | } |
1640 | 1646 | ||
@@ -1646,7 +1652,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1646 | if (tty->ops->close) | 1652 | if (tty->ops->close) |
1647 | tty->ops->close(tty, filp); | 1653 | tty->ops->close(tty, filp); |
1648 | 1654 | ||
1649 | tty_unlock(); | 1655 | tty_unlock(tty); |
1650 | /* | 1656 | /* |
1651 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1657 | * Sanity check: if tty->count is going to zero, there shouldn't be |
1652 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1658 | * any waiters on tty->read_wait or tty->write_wait. We test the |
@@ -1669,7 +1675,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1669 | opens on /dev/tty */ | 1675 | opens on /dev/tty */ |
1670 | 1676 | ||
1671 | mutex_lock(&tty_mutex); | 1677 | mutex_lock(&tty_mutex); |
1672 | tty_lock(); | 1678 | tty_lock_pair(tty, o_tty); |
1673 | tty_closing = tty->count <= 1; | 1679 | tty_closing = tty->count <= 1; |
1674 | o_tty_closing = o_tty && | 1680 | o_tty_closing = o_tty && |
1675 | (o_tty->count <= (pty_master ? 1 : 0)); | 1681 | (o_tty->count <= (pty_master ? 1 : 0)); |
@@ -1700,7 +1706,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1700 | 1706 | ||
1701 | printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", | 1707 | printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", |
1702 | __func__, tty_name(tty, buf)); | 1708 | __func__, tty_name(tty, buf)); |
1703 | tty_unlock(); | 1709 | tty_unlock_pair(tty, o_tty); |
1704 | mutex_unlock(&tty_mutex); | 1710 | mutex_unlock(&tty_mutex); |
1705 | schedule(); | 1711 | schedule(); |
1706 | } | 1712 | } |
@@ -1763,7 +1769,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1763 | } | 1769 | } |
1764 | 1770 | ||
1765 | mutex_unlock(&tty_mutex); | 1771 | mutex_unlock(&tty_mutex); |
1766 | tty_unlock(); | 1772 | tty_unlock_pair(tty, o_tty); |
1767 | /* At this point the TTY_CLOSING flag should ensure a dead tty | 1773 | /* At this point the TTY_CLOSING flag should ensure a dead tty |
1768 | cannot be re-opened by a racing opener */ | 1774 | cannot be re-opened by a racing opener */ |
1769 | 1775 | ||
@@ -1780,7 +1786,9 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1780 | tty_ldisc_release(tty, o_tty); | 1786 | tty_ldisc_release(tty, o_tty); |
1781 | /* | 1787 | /* |
1782 | * The release_tty function takes care of the details of clearing | 1788 | * The release_tty function takes care of the details of clearing |
1783 | * the slots and preserving the termios structure. | 1789 | * the slots and preserving the termios structure. The tty_unlock_pair |
1790 | * should be safe as we keep a kref while the tty is locked (so the | ||
1791 | * unlock never unlocks a freed tty). | ||
1784 | */ | 1792 | */ |
1785 | mutex_lock(&tty_mutex); | 1793 | mutex_lock(&tty_mutex); |
1786 | release_tty(tty, idx); | 1794 | release_tty(tty, idx); |
@@ -1789,7 +1797,6 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1789 | /* Make this pty number available for reallocation */ | 1797 | /* Make this pty number available for reallocation */ |
1790 | if (devpts) | 1798 | if (devpts) |
1791 | devpts_kill_index(inode, idx); | 1799 | devpts_kill_index(inode, idx); |
1792 | |||
1793 | return 0; | 1800 | return 0; |
1794 | } | 1801 | } |
1795 | 1802 | ||
@@ -1893,6 +1900,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, | |||
1893 | * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. | 1900 | * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. |
1894 | * tty->count should protect the rest. | 1901 | * tty->count should protect the rest. |
1895 | * ->siglock protects ->signal/->sighand | 1902 | * ->siglock protects ->signal/->sighand |
1903 | * | ||
1904 | * Note: the tty_unlock/lock cases without a ref are only safe due to | ||
1905 | * tty_mutex | ||
1896 | */ | 1906 | */ |
1897 | 1907 | ||
1898 | static int tty_open(struct inode *inode, struct file *filp) | 1908 | static int tty_open(struct inode *inode, struct file *filp) |
@@ -1916,8 +1926,7 @@ retry_open: | |||
1916 | retval = 0; | 1926 | retval = 0; |
1917 | 1927 | ||
1918 | mutex_lock(&tty_mutex); | 1928 | mutex_lock(&tty_mutex); |
1919 | tty_lock(); | 1929 | /* This is protected by the tty_mutex */ |
1920 | |||
1921 | tty = tty_open_current_tty(device, filp); | 1930 | tty = tty_open_current_tty(device, filp); |
1922 | if (IS_ERR(tty)) { | 1931 | if (IS_ERR(tty)) { |
1923 | retval = PTR_ERR(tty); | 1932 | retval = PTR_ERR(tty); |
@@ -1938,17 +1947,19 @@ retry_open: | |||
1938 | } | 1947 | } |
1939 | 1948 | ||
1940 | if (tty) { | 1949 | if (tty) { |
1950 | tty_lock(tty); | ||
1941 | retval = tty_reopen(tty); | 1951 | retval = tty_reopen(tty); |
1942 | if (retval) | 1952 | if (retval < 0) { |
1953 | tty_unlock(tty); | ||
1943 | tty = ERR_PTR(retval); | 1954 | tty = ERR_PTR(retval); |
1944 | } else | 1955 | } |
1956 | } else /* Returns with the tty_lock held for now */ | ||
1945 | tty = tty_init_dev(driver, index); | 1957 | tty = tty_init_dev(driver, index); |
1946 | 1958 | ||
1947 | mutex_unlock(&tty_mutex); | 1959 | mutex_unlock(&tty_mutex); |
1948 | if (driver) | 1960 | if (driver) |
1949 | tty_driver_kref_put(driver); | 1961 | tty_driver_kref_put(driver); |
1950 | if (IS_ERR(tty)) { | 1962 | if (IS_ERR(tty)) { |
1951 | tty_unlock(); | ||
1952 | retval = PTR_ERR(tty); | 1963 | retval = PTR_ERR(tty); |
1953 | goto err_file; | 1964 | goto err_file; |
1954 | } | 1965 | } |
@@ -1977,7 +1988,7 @@ retry_open: | |||
1977 | printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, | 1988 | printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, |
1978 | retval, tty->name); | 1989 | retval, tty->name); |
1979 | #endif | 1990 | #endif |
1980 | tty_unlock(); /* need to call tty_release without BTM */ | 1991 | tty_unlock(tty); /* need to call tty_release without BTM */ |
1981 | tty_release(inode, filp); | 1992 | tty_release(inode, filp); |
1982 | if (retval != -ERESTARTSYS) | 1993 | if (retval != -ERESTARTSYS) |
1983 | return retval; | 1994 | return retval; |
@@ -1989,17 +2000,15 @@ retry_open: | |||
1989 | /* | 2000 | /* |
1990 | * Need to reset f_op in case a hangup happened. | 2001 | * Need to reset f_op in case a hangup happened. |
1991 | */ | 2002 | */ |
1992 | tty_lock(); | ||
1993 | if (filp->f_op == &hung_up_tty_fops) | 2003 | if (filp->f_op == &hung_up_tty_fops) |
1994 | filp->f_op = &tty_fops; | 2004 | filp->f_op = &tty_fops; |
1995 | tty_unlock(); | ||
1996 | goto retry_open; | 2005 | goto retry_open; |
1997 | } | 2006 | } |
1998 | tty_unlock(); | 2007 | tty_unlock(tty); |
1999 | 2008 | ||
2000 | 2009 | ||
2001 | mutex_lock(&tty_mutex); | 2010 | mutex_lock(&tty_mutex); |
2002 | tty_lock(); | 2011 | tty_lock(tty); |
2003 | spin_lock_irq(¤t->sighand->siglock); | 2012 | spin_lock_irq(¤t->sighand->siglock); |
2004 | if (!noctty && | 2013 | if (!noctty && |
2005 | current->signal->leader && | 2014 | current->signal->leader && |
@@ -2007,11 +2016,10 @@ retry_open: | |||
2007 | tty->session == NULL) | 2016 | tty->session == NULL) |
2008 | __proc_set_tty(current, tty); | 2017 | __proc_set_tty(current, tty); |
2009 | spin_unlock_irq(¤t->sighand->siglock); | 2018 | spin_unlock_irq(¤t->sighand->siglock); |
2010 | tty_unlock(); | 2019 | tty_unlock(tty); |
2011 | mutex_unlock(&tty_mutex); | 2020 | mutex_unlock(&tty_mutex); |
2012 | return 0; | 2021 | return 0; |
2013 | err_unlock: | 2022 | err_unlock: |
2014 | tty_unlock(); | ||
2015 | mutex_unlock(&tty_mutex); | 2023 | mutex_unlock(&tty_mutex); |
2016 | /* after locks to avoid deadlock */ | 2024 | /* after locks to avoid deadlock */ |
2017 | if (!IS_ERR_OR_NULL(driver)) | 2025 | if (!IS_ERR_OR_NULL(driver)) |
@@ -2094,10 +2102,13 @@ out: | |||
2094 | 2102 | ||
2095 | static int tty_fasync(int fd, struct file *filp, int on) | 2103 | static int tty_fasync(int fd, struct file *filp, int on) |
2096 | { | 2104 | { |
2105 | struct tty_struct *tty = file_tty(filp); | ||
2097 | int retval; | 2106 | int retval; |
2098 | tty_lock(); | 2107 | |
2108 | tty_lock(tty); | ||
2099 | retval = __tty_fasync(fd, filp, on); | 2109 | retval = __tty_fasync(fd, filp, on); |
2100 | tty_unlock(); | 2110 | tty_unlock(tty); |
2111 | |||
2101 | return retval; | 2112 | return retval; |
2102 | } | 2113 | } |
2103 | 2114 | ||
@@ -2934,6 +2945,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2934 | tty->pgrp = NULL; | 2945 | tty->pgrp = NULL; |
2935 | tty->overrun_time = jiffies; | 2946 | tty->overrun_time = jiffies; |
2936 | tty_buffer_init(tty); | 2947 | tty_buffer_init(tty); |
2948 | mutex_init(&tty->legacy_mutex); | ||
2937 | mutex_init(&tty->termios_mutex); | 2949 | mutex_init(&tty->termios_mutex); |
2938 | mutex_init(&tty->ldisc_mutex); | 2950 | mutex_init(&tty->ldisc_mutex); |
2939 | init_waitqueue_head(&tty->write_wait); | 2951 | init_waitqueue_head(&tty->write_wait); |
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 3d0687197d09..4d7b56268c79 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -568,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
568 | if (IS_ERR(new_ldisc)) | 568 | if (IS_ERR(new_ldisc)) |
569 | return PTR_ERR(new_ldisc); | 569 | return PTR_ERR(new_ldisc); |
570 | 570 | ||
571 | tty_lock(); | 571 | tty_lock(tty); |
572 | /* | 572 | /* |
573 | * We need to look at the tty locking here for pty/tty pairs | 573 | * We need to look at the tty locking here for pty/tty pairs |
574 | * when both sides try to change in parallel. | 574 | * when both sides try to change in parallel. |
@@ -582,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
582 | */ | 582 | */ |
583 | 583 | ||
584 | if (tty->ldisc->ops->num == ldisc) { | 584 | if (tty->ldisc->ops->num == ldisc) { |
585 | tty_unlock(); | 585 | tty_unlock(tty); |
586 | tty_ldisc_put(new_ldisc); | 586 | tty_ldisc_put(new_ldisc); |
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | 589 | ||
590 | tty_unlock(); | 590 | tty_unlock(tty); |
591 | /* | 591 | /* |
592 | * Problem: What do we do if this blocks ? | 592 | * Problem: What do we do if this blocks ? |
593 | * We could deadlock here | 593 | * We could deadlock here |
@@ -595,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
595 | 595 | ||
596 | tty_wait_until_sent(tty, 0); | 596 | tty_wait_until_sent(tty, 0); |
597 | 597 | ||
598 | tty_lock(); | 598 | tty_lock(tty); |
599 | mutex_lock(&tty->ldisc_mutex); | 599 | mutex_lock(&tty->ldisc_mutex); |
600 | 600 | ||
601 | /* | 601 | /* |
@@ -605,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
605 | 605 | ||
606 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | 606 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
607 | mutex_unlock(&tty->ldisc_mutex); | 607 | mutex_unlock(&tty->ldisc_mutex); |
608 | tty_unlock(); | 608 | tty_unlock(tty); |
609 | wait_event(tty_ldisc_wait, | 609 | wait_event(tty_ldisc_wait, |
610 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 610 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
611 | tty_lock(); | 611 | tty_lock(tty); |
612 | mutex_lock(&tty->ldisc_mutex); | 612 | mutex_lock(&tty->ldisc_mutex); |
613 | } | 613 | } |
614 | 614 | ||
@@ -623,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
623 | 623 | ||
624 | o_ldisc = tty->ldisc; | 624 | o_ldisc = tty->ldisc; |
625 | 625 | ||
626 | tty_unlock(); | 626 | tty_unlock(tty); |
627 | /* | 627 | /* |
628 | * Make sure we don't change while someone holds a | 628 | * Make sure we don't change while someone holds a |
629 | * reference to the line discipline. The TTY_LDISC bit | 629 | * reference to the line discipline. The TTY_LDISC bit |
@@ -650,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
650 | 650 | ||
651 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); | 651 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); |
652 | 652 | ||
653 | tty_lock(); | 653 | tty_lock(tty); |
654 | mutex_lock(&tty->ldisc_mutex); | 654 | mutex_lock(&tty->ldisc_mutex); |
655 | 655 | ||
656 | /* handle wait idle failure locked */ | 656 | /* handle wait idle failure locked */ |
@@ -665,7 +665,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
665 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 665 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
666 | mutex_unlock(&tty->ldisc_mutex); | 666 | mutex_unlock(&tty->ldisc_mutex); |
667 | tty_ldisc_put(new_ldisc); | 667 | tty_ldisc_put(new_ldisc); |
668 | tty_unlock(); | 668 | tty_unlock(tty); |
669 | return -EIO; | 669 | return -EIO; |
670 | } | 670 | } |
671 | 671 | ||
@@ -708,7 +708,7 @@ enable: | |||
708 | if (o_work) | 708 | if (o_work) |
709 | schedule_work(&o_tty->buf.work); | 709 | schedule_work(&o_tty->buf.work); |
710 | mutex_unlock(&tty->ldisc_mutex); | 710 | mutex_unlock(&tty->ldisc_mutex); |
711 | tty_unlock(); | 711 | tty_unlock(tty); |
712 | return retval; | 712 | return retval; |
713 | } | 713 | } |
714 | 714 | ||
@@ -816,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
816 | * need to wait for another function taking the BTM | 816 | * need to wait for another function taking the BTM |
817 | */ | 817 | */ |
818 | clear_bit(TTY_LDISC, &tty->flags); | 818 | clear_bit(TTY_LDISC, &tty->flags); |
819 | tty_unlock(); | 819 | tty_unlock(tty); |
820 | cancel_work_sync(&tty->buf.work); | 820 | cancel_work_sync(&tty->buf.work); |
821 | mutex_unlock(&tty->ldisc_mutex); | 821 | mutex_unlock(&tty->ldisc_mutex); |
822 | retry: | 822 | retry: |
823 | tty_lock(); | 823 | tty_lock(tty); |
824 | mutex_lock(&tty->ldisc_mutex); | 824 | mutex_lock(&tty->ldisc_mutex); |
825 | 825 | ||
826 | /* At this point we have a closed ldisc and we want to | 826 | /* At this point we have a closed ldisc and we want to |
@@ -831,7 +831,7 @@ retry: | |||
831 | if (atomic_read(&tty->ldisc->users) != 1) { | 831 | if (atomic_read(&tty->ldisc->users) != 1) { |
832 | char cur_n[TASK_COMM_LEN], tty_n[64]; | 832 | char cur_n[TASK_COMM_LEN], tty_n[64]; |
833 | long timeout = 3 * HZ; | 833 | long timeout = 3 * HZ; |
834 | tty_unlock(); | 834 | tty_unlock(tty); |
835 | 835 | ||
836 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { | 836 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { |
837 | timeout = MAX_SCHEDULE_TIMEOUT; | 837 | timeout = MAX_SCHEDULE_TIMEOUT; |
@@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | |||
894 | tty_ldisc_enable(tty); | 894 | tty_ldisc_enable(tty); |
895 | return 0; | 895 | return 0; |
896 | } | 896 | } |
897 | |||
898 | static void tty_ldisc_kill(struct tty_struct *tty) | ||
899 | { | ||
900 | mutex_lock(&tty->ldisc_mutex); | ||
901 | /* | ||
902 | * Now kill off the ldisc | ||
903 | */ | ||
904 | tty_ldisc_close(tty, tty->ldisc); | ||
905 | tty_ldisc_put(tty->ldisc); | ||
906 | /* Force an oops if we mess this up */ | ||
907 | tty->ldisc = NULL; | ||
908 | |||
909 | /* Ensure the next open requests the N_TTY ldisc */ | ||
910 | tty_set_termios_ldisc(tty, N_TTY); | ||
911 | mutex_unlock(&tty->ldisc_mutex); | ||
912 | } | ||
913 | |||
897 | /** | 914 | /** |
898 | * tty_ldisc_release - release line discipline | 915 | * tty_ldisc_release - release line discipline |
899 | * @tty: tty being shut down | 916 | * @tty: tty being shut down |
@@ -912,29 +929,21 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
912 | * race with the set_ldisc code path. | 929 | * race with the set_ldisc code path. |
913 | */ | 930 | */ |
914 | 931 | ||
932 | tty_lock_pair(tty, o_tty); | ||
915 | tty_ldisc_halt(tty); | 933 | tty_ldisc_halt(tty); |
916 | tty_ldisc_flush_works(tty); | 934 | tty_ldisc_flush_works(tty); |
917 | tty_lock(); | 935 | if (o_tty) { |
918 | 936 | tty_ldisc_halt(o_tty); | |
919 | mutex_lock(&tty->ldisc_mutex); | 937 | tty_ldisc_flush_works(o_tty); |
920 | /* | 938 | } |
921 | * Now kill off the ldisc | ||
922 | */ | ||
923 | tty_ldisc_close(tty, tty->ldisc); | ||
924 | tty_ldisc_put(tty->ldisc); | ||
925 | /* Force an oops if we mess this up */ | ||
926 | tty->ldisc = NULL; | ||
927 | |||
928 | /* Ensure the next open requests the N_TTY ldisc */ | ||
929 | tty_set_termios_ldisc(tty, N_TTY); | ||
930 | mutex_unlock(&tty->ldisc_mutex); | ||
931 | |||
932 | tty_unlock(); | ||
933 | 939 | ||
934 | /* This will need doing differently if we need to lock */ | 940 | /* This will need doing differently if we need to lock */ |
941 | tty_ldisc_kill(tty); | ||
942 | |||
935 | if (o_tty) | 943 | if (o_tty) |
936 | tty_ldisc_release(o_tty, NULL); | 944 | tty_ldisc_kill(o_tty); |
937 | 945 | ||
946 | tty_unlock_pair(tty, o_tty); | ||
938 | /* And the memory resources remaining (buffers, termios) will be | 947 | /* And the memory resources remaining (buffers, termios) will be |
939 | disposed of when the kref hits zero */ | 948 | disposed of when the kref hits zero */ |
940 | } | 949 | } |
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 9ff986c32a21..67feac9e6ebb 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c | |||
@@ -4,29 +4,70 @@ | |||
4 | #include <linux/semaphore.h> | 4 | #include <linux/semaphore.h> |
5 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
6 | 6 | ||
7 | /* | 7 | /* Legacy tty mutex glue */ |
8 | * The 'big tty mutex' | 8 | |
9 | * | 9 | enum { |
10 | * This mutex is taken and released by tty_lock() and tty_unlock(), | 10 | TTY_MUTEX_NORMAL, |
11 | * replacing the older big kernel lock. | 11 | TTY_MUTEX_NESTED, |
12 | * It can no longer be taken recursively, and does not get | 12 | }; |
13 | * released implicitly while sleeping. | ||
14 | * | ||
15 | * Don't use in new code. | ||
16 | */ | ||
17 | static DEFINE_MUTEX(big_tty_mutex); | ||
18 | 13 | ||
19 | /* | 14 | /* |
20 | * Getting the big tty mutex. | 15 | * Getting the big tty mutex. |
21 | */ | 16 | */ |
22 | void __lockfunc tty_lock(void) | 17 | |
18 | static void __lockfunc tty_lock_nested(struct tty_struct *tty, | ||
19 | unsigned int subclass) | ||
23 | { | 20 | { |
24 | mutex_lock(&big_tty_mutex); | 21 | if (tty->magic != TTY_MAGIC) { |
22 | printk(KERN_ERR "L Bad %p\n", tty); | ||
23 | WARN_ON(1); | ||
24 | return; | ||
25 | } | ||
26 | tty_kref_get(tty); | ||
27 | mutex_lock_nested(&tty->legacy_mutex, subclass); | ||
28 | } | ||
29 | |||
30 | void __lockfunc tty_lock(struct tty_struct *tty) | ||
31 | { | ||
32 | return tty_lock_nested(tty, TTY_MUTEX_NORMAL); | ||
25 | } | 33 | } |
26 | EXPORT_SYMBOL(tty_lock); | 34 | EXPORT_SYMBOL(tty_lock); |
27 | 35 | ||
28 | void __lockfunc tty_unlock(void) | 36 | void __lockfunc tty_unlock(struct tty_struct *tty) |
29 | { | 37 | { |
30 | mutex_unlock(&big_tty_mutex); | 38 | if (tty->magic != TTY_MAGIC) { |
39 | printk(KERN_ERR "U Bad %p\n", tty); | ||
40 | WARN_ON(1); | ||
41 | return; | ||
42 | } | ||
43 | mutex_unlock(&tty->legacy_mutex); | ||
44 | tty_kref_put(tty); | ||
31 | } | 45 | } |
32 | EXPORT_SYMBOL(tty_unlock); | 46 | EXPORT_SYMBOL(tty_unlock); |
47 | |||
48 | /* | ||
49 | * Getting the big tty mutex for a pair of ttys with lock ordering | ||
50 | * On a non pty/tty pair tty2 can be NULL which is just fine. | ||
51 | */ | ||
52 | void __lockfunc tty_lock_pair(struct tty_struct *tty, | ||
53 | struct tty_struct *tty2) | ||
54 | { | ||
55 | if (tty < tty2) { | ||
56 | tty_lock(tty); | ||
57 | tty_lock_nested(tty2, TTY_MUTEX_NESTED); | ||
58 | } else { | ||
59 | if (tty2 && tty2 != tty) | ||
60 | tty_lock(tty2); | ||
61 | tty_lock_nested(tty, TTY_MUTEX_NESTED); | ||
62 | } | ||
63 | } | ||
64 | EXPORT_SYMBOL(tty_lock_pair); | ||
65 | |||
66 | void __lockfunc tty_unlock_pair(struct tty_struct *tty, | ||
67 | struct tty_struct *tty2) | ||
68 | { | ||
69 | tty_unlock(tty); | ||
70 | if (tty2 && tty2 != tty) | ||
71 | tty_unlock(tty2); | ||
72 | } | ||
73 | EXPORT_SYMBOL(tty_unlock_pair); | ||
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index edcb827c1286..5246763cff0c 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
@@ -239,7 +239,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
239 | 239 | ||
240 | /* block if port is in the process of being closed */ | 240 | /* block if port is in the process of being closed */ |
241 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 241 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
242 | wait_event_interruptible_tty(port->close_wait, | 242 | wait_event_interruptible_tty(tty, port->close_wait, |
243 | !(port->flags & ASYNC_CLOSING)); | 243 | !(port->flags & ASYNC_CLOSING)); |
244 | if (port->flags & ASYNC_HUP_NOTIFY) | 244 | if (port->flags & ASYNC_HUP_NOTIFY) |
245 | return -EAGAIN; | 245 | return -EAGAIN; |
@@ -305,9 +305,9 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
305 | retval = -ERESTARTSYS; | 305 | retval = -ERESTARTSYS; |
306 | break; | 306 | break; |
307 | } | 307 | } |
308 | tty_unlock(); | 308 | tty_unlock(tty); |
309 | schedule(); | 309 | schedule(); |
310 | tty_lock(); | 310 | tty_lock(tty); |
311 | } | 311 | } |
312 | finish_wait(&port->open_wait, &wait); | 312 | finish_wait(&port->open_wait, &wait); |
313 | 313 | ||
diff --git a/include/linux/tty.h b/include/linux/tty.h index a39e72325e78..acca24bf06a7 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -268,6 +268,7 @@ struct tty_struct { | |||
268 | struct mutex ldisc_mutex; | 268 | struct mutex ldisc_mutex; |
269 | struct tty_ldisc *ldisc; | 269 | struct tty_ldisc *ldisc; |
270 | 270 | ||
271 | struct mutex legacy_mutex; | ||
271 | struct mutex termios_mutex; | 272 | struct mutex termios_mutex; |
272 | spinlock_t ctrl_lock; | 273 | spinlock_t ctrl_lock; |
273 | /* Termios values are protected by the termios mutex */ | 274 | /* Termios values are protected by the termios mutex */ |
@@ -609,8 +610,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty, | |||
609 | 610 | ||
610 | /* tty_mutex.c */ | 611 | /* tty_mutex.c */ |
611 | /* functions for preparation of BKL removal */ | 612 | /* functions for preparation of BKL removal */ |
612 | extern void __lockfunc tty_lock(void) __acquires(tty_lock); | 613 | extern void __lockfunc tty_lock(struct tty_struct *tty); |
613 | extern void __lockfunc tty_unlock(void) __releases(tty_lock); | 614 | extern void __lockfunc tty_unlock(struct tty_struct *tty); |
615 | extern void __lockfunc tty_lock_pair(struct tty_struct *tty, | ||
616 | struct tty_struct *tty2); | ||
617 | extern void __lockfunc tty_unlock_pair(struct tty_struct *tty, | ||
618 | struct tty_struct *tty2); | ||
614 | 619 | ||
615 | /* | 620 | /* |
616 | * this shall be called only from where BTM is held (like close) | 621 | * this shall be called only from where BTM is held (like close) |
@@ -625,9 +630,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock); | |||
625 | static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, | 630 | static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, |
626 | long timeout) | 631 | long timeout) |
627 | { | 632 | { |
628 | tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ | 633 | tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */ |
629 | tty_wait_until_sent(tty, timeout); | 634 | tty_wait_until_sent(tty, timeout); |
630 | tty_lock(); | 635 | tty_lock(tty); |
631 | } | 636 | } |
632 | 637 | ||
633 | /* | 638 | /* |
@@ -642,16 +647,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, | |||
642 | * | 647 | * |
643 | * Do not use in new code. | 648 | * Do not use in new code. |
644 | */ | 649 | */ |
645 | #define wait_event_interruptible_tty(wq, condition) \ | 650 | #define wait_event_interruptible_tty(tty, wq, condition) \ |
646 | ({ \ | 651 | ({ \ |
647 | int __ret = 0; \ | 652 | int __ret = 0; \ |
648 | if (!(condition)) { \ | 653 | if (!(condition)) { \ |
649 | __wait_event_interruptible_tty(wq, condition, __ret); \ | 654 | __wait_event_interruptible_tty(tty, wq, condition, __ret); \ |
650 | } \ | 655 | } \ |
651 | __ret; \ | 656 | __ret; \ |
652 | }) | 657 | }) |
653 | 658 | ||
654 | #define __wait_event_interruptible_tty(wq, condition, ret) \ | 659 | #define __wait_event_interruptible_tty(tty, wq, condition, ret) \ |
655 | do { \ | 660 | do { \ |
656 | DEFINE_WAIT(__wait); \ | 661 | DEFINE_WAIT(__wait); \ |
657 | \ | 662 | \ |
@@ -660,9 +665,9 @@ do { \ | |||
660 | if (condition) \ | 665 | if (condition) \ |
661 | break; \ | 666 | break; \ |
662 | if (!signal_pending(current)) { \ | 667 | if (!signal_pending(current)) { \ |
663 | tty_unlock(); \ | 668 | tty_unlock(tty); \ |
664 | schedule(); \ | 669 | schedule(); \ |
665 | tty_lock(); \ | 670 | tty_lock(tty); \ |
666 | continue; \ | 671 | continue; \ |
667 | } \ | 672 | } \ |
668 | ret = -ERESTARTSYS; \ | 673 | ret = -ERESTARTSYS; \ |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 87ddd051881b..b54c86a2e66b 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -705,9 +705,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
705 | break; | 705 | break; |
706 | } | 706 | } |
707 | 707 | ||
708 | tty_unlock(); | 708 | tty_unlock(tty); |
709 | schedule(); | 709 | schedule(); |
710 | tty_lock(); | 710 | tty_lock(tty); |
711 | } | 711 | } |
712 | set_current_state(TASK_RUNNING); | 712 | set_current_state(TASK_RUNNING); |
713 | remove_wait_queue(&dev->wait, &wait); | 713 | remove_wait_queue(&dev->wait, &wait); |