diff options
| -rw-r--r-- | drivers/staging/serial/68360serial.c | 4 | ||||
| -rw-r--r-- | drivers/tty/amiserial.c | 12 | ||||
| -rw-r--r-- | drivers/tty/cyclades.c | 2 | ||||
| -rw-r--r-- | drivers/tty/n_r3964.c | 11 | ||||
| -rw-r--r-- | drivers/tty/pty.c | 23 | ||||
| -rw-r--r-- | drivers/tty/serial/crisv10.c | 4 | ||||
| -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 | 67 | ||||
| -rw-r--r-- | drivers/tty/tty_ldisc.c | 30 | ||||
| -rw-r--r-- | drivers/tty/tty_mutex.c | 60 | ||||
| -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 |
15 files changed, 155 insertions, 103 deletions
diff --git a/drivers/staging/serial/68360serial.c b/drivers/staging/serial/68360serial.c index daf0b1d0dc28..23ee50e25e44 100644 --- a/drivers/staging/serial/68360serial.c +++ b/drivers/staging/serial/68360serial.c | |||
| @@ -1859,9 +1859,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
| 1859 | printk("block_til_ready blocking: ttys%d, count = %d\n", | 1859 | printk("block_til_ready blocking: ttys%d, count = %d\n", |
| 1860 | info->line, state->count); | 1860 | info->line, state->count); |
| 1861 | #endif | 1861 | #endif |
| 1862 | tty_unlock(); | 1862 | tty_unlock(tty); |
| 1863 | schedule(); | 1863 | schedule(); |
| 1864 | tty_lock(); | 1864 | tty_lock(tty); |
| 1865 | } | 1865 | } |
| 1866 | current->state = TASK_RUNNING; | 1866 | current->state = TASK_RUNNING; |
| 1867 | remove_wait_queue(&info->open_wait, &wait); | 1867 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 6cc4358f68c1..b88a65c49240 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 | ||
| @@ -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 e61cabdd69df..6984e1a2686a 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..656ad93bbc96 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c | |||
| @@ -1065,7 +1065,8 @@ 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 | /* FIXME: should use a private lock */ |
| 1069 | tty_lock(tty); | ||
| 1069 | 1070 | ||
| 1070 | pClient = findClient(pInfo, task_pid(current)); | 1071 | pClient = findClient(pInfo, task_pid(current)); |
| 1071 | if (pClient) { | 1072 | if (pClient) { |
| @@ -1077,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
| 1077 | goto unlock; | 1078 | goto unlock; |
| 1078 | } | 1079 | } |
| 1079 | /* block until there is a message: */ | 1080 | /* block until there is a message: */ |
| 1080 | wait_event_interruptible_tty(pInfo->read_wait, | 1081 | wait_event_interruptible_tty(tty, pInfo->read_wait, |
| 1081 | (pMsg = remove_msg(pInfo, pClient))); | 1082 | (pMsg = remove_msg(pInfo, pClient))); |
| 1082 | } | 1083 | } |
| 1083 | 1084 | ||
| @@ -1107,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
| 1107 | } | 1108 | } |
| 1108 | ret = -EPERM; | 1109 | ret = -EPERM; |
| 1109 | unlock: | 1110 | unlock: |
| 1110 | tty_unlock(); | 1111 | tty_unlock(tty); |
| 1111 | return ret; | 1112 | return ret; |
| 1112 | } | 1113 | } |
| 1113 | 1114 | ||
| @@ -1156,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
| 1156 | pHeader->locks = 0; | 1157 | pHeader->locks = 0; |
| 1157 | pHeader->owner = NULL; | 1158 | pHeader->owner = NULL; |
| 1158 | 1159 | ||
| 1159 | tty_lock(); | 1160 | tty_lock(tty); |
| 1160 | 1161 | ||
| 1161 | pClient = findClient(pInfo, task_pid(current)); | 1162 | pClient = findClient(pInfo, task_pid(current)); |
| 1162 | if (pClient) { | 1163 | if (pClient) { |
| @@ -1175,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
| 1175 | add_tx_queue(pInfo, pHeader); | 1176 | add_tx_queue(pInfo, pHeader); |
| 1176 | trigger_transmit(pInfo); | 1177 | trigger_transmit(pInfo); |
| 1177 | 1178 | ||
| 1178 | tty_unlock(); | 1179 | tty_unlock(tty); |
| 1179 | 1180 | ||
| 1180 | return 0; | 1181 | return 0; |
| 1181 | } | 1182 | } |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 5505ffc91da4..d6fa8429f3ff 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,7 @@ 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_vhangup(tty->link); | 66 | tty_vhangup(tty->link); |
| 67 | tty_lock(); | ||
| 68 | } | 67 | } |
| 69 | } | 68 | } |
| 70 | 69 | ||
| @@ -622,26 +621,29 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
| 622 | return retval; | 621 | return retval; |
| 623 | 622 | ||
| 624 | /* find a device that is not in use. */ | 623 | /* find a device that is not in use. */ |
| 625 | tty_lock(); | 624 | mutex_lock(&devpts_mutex); |
| 626 | index = devpts_new_index(inode); | 625 | index = devpts_new_index(inode); |
| 627 | tty_unlock(); | ||
| 628 | if (index < 0) { | 626 | if (index < 0) { |
| 629 | retval = index; | 627 | retval = index; |
| 630 | goto err_file; | 628 | goto err_file; |
| 631 | } | 629 | } |
| 632 | 630 | ||
| 631 | mutex_unlock(&devpts_mutex); | ||
| 632 | |||
| 633 | mutex_lock(&tty_mutex); | 633 | mutex_lock(&tty_mutex); |
| 634 | mutex_lock(&devpts_mutex); | 634 | mutex_lock(&devpts_mutex); |
| 635 | tty = tty_init_dev(ptm_driver, index); | 635 | tty = tty_init_dev(ptm_driver, index); |
| 636 | mutex_unlock(&devpts_mutex); | ||
| 637 | tty_lock(); | ||
| 638 | mutex_unlock(&tty_mutex); | ||
| 639 | 636 | ||
| 640 | if (IS_ERR(tty)) { | 637 | if (IS_ERR(tty)) { |
| 641 | retval = PTR_ERR(tty); | 638 | retval = PTR_ERR(tty); |
| 642 | goto out; | 639 | goto out; |
| 643 | } | 640 | } |
| 644 | 641 | ||
| 642 | /* The tty returned here is locked so we can safely | ||
| 643 | drop the mutex */ | ||
| 644 | mutex_unlock(&devpts_mutex); | ||
| 645 | mutex_unlock(&tty_mutex); | ||
| 646 | |||
| 645 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 647 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
| 646 | 648 | ||
| 647 | tty_add_file(tty, filp); | 649 | tty_add_file(tty, filp); |
| @@ -654,16 +656,17 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
| 654 | if (retval) | 656 | if (retval) |
| 655 | goto err_release; | 657 | goto err_release; |
| 656 | 658 | ||
| 657 | tty_unlock(); | 659 | tty_unlock(tty); |
| 658 | return 0; | 660 | return 0; |
| 659 | err_release: | 661 | err_release: |
| 660 | tty_unlock(); | 662 | tty_unlock(tty); |
| 661 | tty_release(inode, filp); | 663 | tty_release(inode, filp); |
| 662 | return retval; | 664 | return retval; |
| 663 | out: | 665 | out: |
| 666 | mutex_unlock(&tty_mutex); | ||
| 664 | devpts_kill_index(inode, index); | 667 | devpts_kill_index(inode, index); |
| 665 | tty_unlock(); | ||
| 666 | err_file: | 668 | err_file: |
| 669 | mutex_unlock(&devpts_mutex); | ||
| 667 | tty_free_file(filp); | 670 | tty_free_file(filp); |
| 668 | return retval; | 671 | return retval; |
| 669 | } | 672 | } |
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 80b6b1b1f725..b431a5164f45 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c | |||
| @@ -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); |
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 593d40ad0a6b..5ed0daae6564 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 aa1debf97cc7..45b43f11ca39 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 a3dddc12d2fe..4a1e4f07765b 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 b425c79675ad..9e930c009bf2 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
| @@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty) | |||
| 185 | put_device(tty->dev); | 185 | put_device(tty->dev); |
| 186 | kfree(tty->write_buf); | 186 | kfree(tty->write_buf); |
| 187 | tty_buffer_free_all(tty); | 187 | tty_buffer_free_all(tty); |
| 188 | tty->magic = 0xDEADDEAD; | ||
| 188 | kfree(tty); | 189 | kfree(tty); |
| 189 | } | 190 | } |
| 190 | 191 | ||
| @@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
| 573 | } | 574 | } |
| 574 | spin_unlock(&redirect_lock); | 575 | spin_unlock(&redirect_lock); |
| 575 | 576 | ||
| 576 | tty_lock(); | 577 | tty_lock(tty); |
| 577 | 578 | ||
| 578 | /* some functions below drop BTM, so we need this bit */ | 579 | /* some functions below drop BTM, so we need this bit */ |
| 579 | set_bit(TTY_HUPPING, &tty->flags); | 580 | set_bit(TTY_HUPPING, &tty->flags); |
| @@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
| 666 | clear_bit(TTY_HUPPING, &tty->flags); | 667 | clear_bit(TTY_HUPPING, &tty->flags); |
| 667 | tty_ldisc_enable(tty); | 668 | tty_ldisc_enable(tty); |
| 668 | 669 | ||
| 669 | tty_unlock(); | 670 | tty_unlock(tty); |
| 670 | 671 | ||
| 671 | if (f) | 672 | if (f) |
| 672 | fput(f); | 673 | fput(f); |
| @@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
| 1103 | { | 1104 | { |
| 1104 | if (tty) { | 1105 | if (tty) { |
| 1105 | mutex_lock(&tty->atomic_write_lock); | 1106 | mutex_lock(&tty->atomic_write_lock); |
| 1106 | tty_lock(); | 1107 | tty_lock(tty); |
| 1107 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | 1108 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { |
| 1108 | tty_unlock(); | 1109 | tty_unlock(tty); |
| 1109 | tty->ops->write(tty, msg, strlen(msg)); | 1110 | tty->ops->write(tty, msg, strlen(msg)); |
| 1110 | } else | 1111 | } else |
| 1111 | tty_unlock(); | 1112 | tty_unlock(tty); |
| 1112 | tty_write_unlock(tty); | 1113 | tty_write_unlock(tty); |
| 1113 | } | 1114 | } |
| 1114 | return; | 1115 | 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; |
| @@ -1415,9 +1417,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) | |||
| 1415 | retval = tty_ldisc_setup(tty, tty->link); | 1417 | retval = tty_ldisc_setup(tty, tty->link); |
| 1416 | if (retval) | 1418 | if (retval) |
| 1417 | goto err_release_tty; | 1419 | goto err_release_tty; |
| 1420 | /* Return the tty locked so that it cannot vanish under the caller */ | ||
| 1418 | return tty; | 1421 | return tty; |
| 1419 | 1422 | ||
| 1420 | err_deinit_tty: | 1423 | err_deinit_tty: |
| 1424 | tty_unlock(tty); | ||
| 1421 | deinitialize_tty_struct(tty); | 1425 | deinitialize_tty_struct(tty); |
| 1422 | free_tty_struct(tty); | 1426 | free_tty_struct(tty); |
| 1423 | err_module_put: | 1427 | err_module_put: |
| @@ -1426,6 +1430,7 @@ err_module_put: | |||
| 1426 | 1430 | ||
| 1427 | /* call the tty release_tty routine to clean out this slot */ | 1431 | /* call the tty release_tty routine to clean out this slot */ |
| 1428 | err_release_tty: | 1432 | err_release_tty: |
| 1433 | tty_unlock(tty); | ||
| 1429 | printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " | 1434 | printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " |
| 1430 | "clearing slot %d\n", idx); | 1435 | "clearing slot %d\n", idx); |
| 1431 | release_tty(tty, idx); | 1436 | release_tty(tty, idx); |
| @@ -1628,7 +1633,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1628 | if (tty_paranoia_check(tty, inode, __func__)) | 1633 | if (tty_paranoia_check(tty, inode, __func__)) |
| 1629 | return 0; | 1634 | return 0; |
| 1630 | 1635 | ||
| 1631 | tty_lock(); | 1636 | tty_lock(tty); |
| 1632 | check_tty_count(tty, __func__); | 1637 | check_tty_count(tty, __func__); |
| 1633 | 1638 | ||
| 1634 | __tty_fasync(-1, filp, 0); | 1639 | __tty_fasync(-1, filp, 0); |
| @@ -1637,10 +1642,11 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1637 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1642 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
| 1638 | tty->driver->subtype == PTY_TYPE_MASTER); | 1643 | tty->driver->subtype == PTY_TYPE_MASTER); |
| 1639 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; | 1644 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; |
| 1645 | /* Review: parallel close */ | ||
| 1640 | o_tty = tty->link; | 1646 | o_tty = tty->link; |
| 1641 | 1647 | ||
| 1642 | if (tty_release_checks(tty, o_tty, idx)) { | 1648 | if (tty_release_checks(tty, o_tty, idx)) { |
| 1643 | tty_unlock(); | 1649 | tty_unlock(tty); |
| 1644 | return 0; | 1650 | return 0; |
| 1645 | } | 1651 | } |
| 1646 | 1652 | ||
| @@ -1652,7 +1658,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1652 | if (tty->ops->close) | 1658 | if (tty->ops->close) |
| 1653 | tty->ops->close(tty, filp); | 1659 | tty->ops->close(tty, filp); |
| 1654 | 1660 | ||
| 1655 | tty_unlock(); | 1661 | tty_unlock(tty); |
| 1656 | /* | 1662 | /* |
| 1657 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1663 | * Sanity check: if tty->count is going to zero, there shouldn't be |
| 1658 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1664 | * any waiters on tty->read_wait or tty->write_wait. We test the |
| @@ -1675,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1675 | opens on /dev/tty */ | 1681 | opens on /dev/tty */ |
| 1676 | 1682 | ||
| 1677 | mutex_lock(&tty_mutex); | 1683 | mutex_lock(&tty_mutex); |
| 1678 | tty_lock(); | 1684 | tty_lock_pair(tty, o_tty); |
| 1679 | tty_closing = tty->count <= 1; | 1685 | tty_closing = tty->count <= 1; |
| 1680 | o_tty_closing = o_tty && | 1686 | o_tty_closing = o_tty && |
| 1681 | (o_tty->count <= (pty_master ? 1 : 0)); | 1687 | (o_tty->count <= (pty_master ? 1 : 0)); |
| @@ -1706,7 +1712,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1706 | 1712 | ||
| 1707 | printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", | 1713 | printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", |
| 1708 | __func__, tty_name(tty, buf)); | 1714 | __func__, tty_name(tty, buf)); |
| 1709 | tty_unlock(); | 1715 | tty_unlock_pair(tty, o_tty); |
| 1710 | mutex_unlock(&tty_mutex); | 1716 | mutex_unlock(&tty_mutex); |
| 1711 | schedule(); | 1717 | schedule(); |
| 1712 | } | 1718 | } |
| @@ -1769,7 +1775,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1769 | 1775 | ||
| 1770 | /* check whether both sides are closing ... */ | 1776 | /* check whether both sides are closing ... */ |
| 1771 | if (!tty_closing || (o_tty && !o_tty_closing)) { | 1777 | if (!tty_closing || (o_tty && !o_tty_closing)) { |
| 1772 | tty_unlock(); | 1778 | tty_unlock_pair(tty, o_tty); |
| 1773 | return 0; | 1779 | return 0; |
| 1774 | } | 1780 | } |
| 1775 | 1781 | ||
| @@ -1782,14 +1788,16 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1782 | tty_ldisc_release(tty, o_tty); | 1788 | tty_ldisc_release(tty, o_tty); |
| 1783 | /* | 1789 | /* |
| 1784 | * The release_tty function takes care of the details of clearing | 1790 | * The release_tty function takes care of the details of clearing |
| 1785 | * the slots and preserving the termios structure. | 1791 | * the slots and preserving the termios structure. The tty_unlock_pair |
| 1792 | * should be safe as we keep a kref while the tty is locked (so the | ||
| 1793 | * unlock never unlocks a freed tty). | ||
| 1786 | */ | 1794 | */ |
| 1787 | release_tty(tty, idx); | 1795 | release_tty(tty, idx); |
| 1796 | tty_unlock_pair(tty, o_tty); | ||
| 1788 | 1797 | ||
| 1789 | /* Make this pty number available for reallocation */ | 1798 | /* Make this pty number available for reallocation */ |
| 1790 | if (devpts) | 1799 | if (devpts) |
| 1791 | devpts_kill_index(inode, idx); | 1800 | devpts_kill_index(inode, idx); |
| 1792 | tty_unlock(); | ||
| 1793 | return 0; | 1801 | return 0; |
| 1794 | } | 1802 | } |
| 1795 | 1803 | ||
| @@ -1893,6 +1901,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. | 1901 | * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. |
| 1894 | * tty->count should protect the rest. | 1902 | * tty->count should protect the rest. |
| 1895 | * ->siglock protects ->signal/->sighand | 1903 | * ->siglock protects ->signal/->sighand |
| 1904 | * | ||
| 1905 | * Note: the tty_unlock/lock cases without a ref are only safe due to | ||
| 1906 | * tty_mutex | ||
| 1896 | */ | 1907 | */ |
| 1897 | 1908 | ||
| 1898 | static int tty_open(struct inode *inode, struct file *filp) | 1909 | static int tty_open(struct inode *inode, struct file *filp) |
| @@ -1916,8 +1927,7 @@ retry_open: | |||
| 1916 | retval = 0; | 1927 | retval = 0; |
| 1917 | 1928 | ||
| 1918 | mutex_lock(&tty_mutex); | 1929 | mutex_lock(&tty_mutex); |
| 1919 | tty_lock(); | 1930 | /* This is protected by the tty_mutex */ |
| 1920 | |||
| 1921 | tty = tty_open_current_tty(device, filp); | 1931 | tty = tty_open_current_tty(device, filp); |
| 1922 | if (IS_ERR(tty)) { | 1932 | if (IS_ERR(tty)) { |
| 1923 | retval = PTR_ERR(tty); | 1933 | retval = PTR_ERR(tty); |
| @@ -1938,17 +1948,19 @@ retry_open: | |||
| 1938 | } | 1948 | } |
| 1939 | 1949 | ||
| 1940 | if (tty) { | 1950 | if (tty) { |
| 1951 | tty_lock(tty); | ||
| 1941 | retval = tty_reopen(tty); | 1952 | retval = tty_reopen(tty); |
| 1942 | if (retval) | 1953 | if (retval < 0) { |
| 1954 | tty_unlock(tty); | ||
| 1943 | tty = ERR_PTR(retval); | 1955 | tty = ERR_PTR(retval); |
| 1944 | } else | 1956 | } |
| 1957 | } else /* Returns with the tty_lock held for now */ | ||
| 1945 | tty = tty_init_dev(driver, index); | 1958 | tty = tty_init_dev(driver, index); |
| 1946 | 1959 | ||
| 1947 | mutex_unlock(&tty_mutex); | 1960 | mutex_unlock(&tty_mutex); |
| 1948 | if (driver) | 1961 | if (driver) |
| 1949 | tty_driver_kref_put(driver); | 1962 | tty_driver_kref_put(driver); |
| 1950 | if (IS_ERR(tty)) { | 1963 | if (IS_ERR(tty)) { |
| 1951 | tty_unlock(); | ||
| 1952 | retval = PTR_ERR(tty); | 1964 | retval = PTR_ERR(tty); |
| 1953 | goto err_file; | 1965 | goto err_file; |
| 1954 | } | 1966 | } |
| @@ -1977,7 +1989,7 @@ retry_open: | |||
| 1977 | printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, | 1989 | printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, |
| 1978 | retval, tty->name); | 1990 | retval, tty->name); |
| 1979 | #endif | 1991 | #endif |
| 1980 | tty_unlock(); /* need to call tty_release without BTM */ | 1992 | tty_unlock(tty); /* need to call tty_release without BTM */ |
| 1981 | tty_release(inode, filp); | 1993 | tty_release(inode, filp); |
| 1982 | if (retval != -ERESTARTSYS) | 1994 | if (retval != -ERESTARTSYS) |
| 1983 | return retval; | 1995 | return retval; |
| @@ -1989,17 +2001,15 @@ retry_open: | |||
| 1989 | /* | 2001 | /* |
| 1990 | * Need to reset f_op in case a hangup happened. | 2002 | * Need to reset f_op in case a hangup happened. |
| 1991 | */ | 2003 | */ |
| 1992 | tty_lock(); | ||
| 1993 | if (filp->f_op == &hung_up_tty_fops) | 2004 | if (filp->f_op == &hung_up_tty_fops) |
| 1994 | filp->f_op = &tty_fops; | 2005 | filp->f_op = &tty_fops; |
| 1995 | tty_unlock(); | ||
| 1996 | goto retry_open; | 2006 | goto retry_open; |
| 1997 | } | 2007 | } |
| 1998 | tty_unlock(); | 2008 | tty_unlock(tty); |
| 1999 | 2009 | ||
| 2000 | 2010 | ||
| 2001 | mutex_lock(&tty_mutex); | 2011 | mutex_lock(&tty_mutex); |
| 2002 | tty_lock(); | 2012 | tty_lock(tty); |
| 2003 | spin_lock_irq(¤t->sighand->siglock); | 2013 | spin_lock_irq(¤t->sighand->siglock); |
| 2004 | if (!noctty && | 2014 | if (!noctty && |
| 2005 | current->signal->leader && | 2015 | current->signal->leader && |
| @@ -2007,11 +2017,10 @@ retry_open: | |||
| 2007 | tty->session == NULL) | 2017 | tty->session == NULL) |
| 2008 | __proc_set_tty(current, tty); | 2018 | __proc_set_tty(current, tty); |
| 2009 | spin_unlock_irq(¤t->sighand->siglock); | 2019 | spin_unlock_irq(¤t->sighand->siglock); |
| 2010 | tty_unlock(); | 2020 | tty_unlock(tty); |
| 2011 | mutex_unlock(&tty_mutex); | 2021 | mutex_unlock(&tty_mutex); |
| 2012 | return 0; | 2022 | return 0; |
| 2013 | err_unlock: | 2023 | err_unlock: |
| 2014 | tty_unlock(); | ||
| 2015 | mutex_unlock(&tty_mutex); | 2024 | mutex_unlock(&tty_mutex); |
| 2016 | /* after locks to avoid deadlock */ | 2025 | /* after locks to avoid deadlock */ |
| 2017 | if (!IS_ERR_OR_NULL(driver)) | 2026 | if (!IS_ERR_OR_NULL(driver)) |
| @@ -2094,10 +2103,13 @@ out: | |||
| 2094 | 2103 | ||
| 2095 | static int tty_fasync(int fd, struct file *filp, int on) | 2104 | static int tty_fasync(int fd, struct file *filp, int on) |
| 2096 | { | 2105 | { |
| 2106 | struct tty_struct *tty = file_tty(filp); | ||
| 2097 | int retval; | 2107 | int retval; |
| 2098 | tty_lock(); | 2108 | |
| 2109 | tty_lock(tty); | ||
| 2099 | retval = __tty_fasync(fd, filp, on); | 2110 | retval = __tty_fasync(fd, filp, on); |
| 2100 | tty_unlock(); | 2111 | tty_unlock(tty); |
| 2112 | |||
| 2101 | return retval; | 2113 | return retval; |
| 2102 | } | 2114 | } |
| 2103 | 2115 | ||
| @@ -2934,6 +2946,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
| 2934 | tty->pgrp = NULL; | 2946 | tty->pgrp = NULL; |
| 2935 | tty->overrun_time = jiffies; | 2947 | tty->overrun_time = jiffies; |
| 2936 | tty_buffer_init(tty); | 2948 | tty_buffer_init(tty); |
| 2949 | mutex_init(&tty->legacy_mutex); | ||
| 2937 | mutex_init(&tty->termios_mutex); | 2950 | mutex_init(&tty->termios_mutex); |
| 2938 | mutex_init(&tty->ldisc_mutex); | 2951 | mutex_init(&tty->ldisc_mutex); |
| 2939 | init_waitqueue_head(&tty->write_wait); | 2952 | init_waitqueue_head(&tty->write_wait); |
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 24b95db75d84..fa65cde395a4 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
| @@ -567,7 +567,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 567 | if (IS_ERR(new_ldisc)) | 567 | if (IS_ERR(new_ldisc)) |
| 568 | return PTR_ERR(new_ldisc); | 568 | return PTR_ERR(new_ldisc); |
| 569 | 569 | ||
| 570 | tty_lock(); | 570 | tty_lock(tty); |
| 571 | /* | 571 | /* |
| 572 | * We need to look at the tty locking here for pty/tty pairs | 572 | * We need to look at the tty locking here for pty/tty pairs |
| 573 | * when both sides try to change in parallel. | 573 | * when both sides try to change in parallel. |
| @@ -581,12 +581,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 581 | */ | 581 | */ |
| 582 | 582 | ||
| 583 | if (tty->ldisc->ops->num == ldisc) { | 583 | if (tty->ldisc->ops->num == ldisc) { |
| 584 | tty_unlock(); | 584 | tty_unlock(tty); |
| 585 | tty_ldisc_put(new_ldisc); | 585 | tty_ldisc_put(new_ldisc); |
| 586 | return 0; | 586 | return 0; |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | tty_unlock(); | 589 | tty_unlock(tty); |
| 590 | /* | 590 | /* |
| 591 | * Problem: What do we do if this blocks ? | 591 | * Problem: What do we do if this blocks ? |
| 592 | * We could deadlock here | 592 | * We could deadlock here |
| @@ -594,7 +594,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 594 | 594 | ||
| 595 | tty_wait_until_sent(tty, 0); | 595 | tty_wait_until_sent(tty, 0); |
| 596 | 596 | ||
| 597 | tty_lock(); | 597 | tty_lock(tty); |
| 598 | mutex_lock(&tty->ldisc_mutex); | 598 | mutex_lock(&tty->ldisc_mutex); |
| 599 | 599 | ||
| 600 | /* | 600 | /* |
| @@ -604,10 +604,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 604 | 604 | ||
| 605 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | 605 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
| 606 | mutex_unlock(&tty->ldisc_mutex); | 606 | mutex_unlock(&tty->ldisc_mutex); |
| 607 | tty_unlock(); | 607 | tty_unlock(tty); |
| 608 | wait_event(tty_ldisc_wait, | 608 | wait_event(tty_ldisc_wait, |
| 609 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 609 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
| 610 | tty_lock(); | 610 | tty_lock(tty); |
| 611 | mutex_lock(&tty->ldisc_mutex); | 611 | mutex_lock(&tty->ldisc_mutex); |
| 612 | } | 612 | } |
| 613 | 613 | ||
| @@ -622,7 +622,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 622 | 622 | ||
| 623 | o_ldisc = tty->ldisc; | 623 | o_ldisc = tty->ldisc; |
| 624 | 624 | ||
| 625 | tty_unlock(); | 625 | tty_unlock(tty); |
| 626 | /* | 626 | /* |
| 627 | * Make sure we don't change while someone holds a | 627 | * Make sure we don't change while someone holds a |
| 628 | * reference to the line discipline. The TTY_LDISC bit | 628 | * reference to the line discipline. The TTY_LDISC bit |
| @@ -649,7 +649,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 649 | 649 | ||
| 650 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); | 650 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); |
| 651 | 651 | ||
| 652 | tty_lock(); | 652 | tty_lock(tty); |
| 653 | mutex_lock(&tty->ldisc_mutex); | 653 | mutex_lock(&tty->ldisc_mutex); |
| 654 | 654 | ||
| 655 | /* handle wait idle failure locked */ | 655 | /* handle wait idle failure locked */ |
| @@ -664,7 +664,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 664 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 664 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
| 665 | mutex_unlock(&tty->ldisc_mutex); | 665 | mutex_unlock(&tty->ldisc_mutex); |
| 666 | tty_ldisc_put(new_ldisc); | 666 | tty_ldisc_put(new_ldisc); |
| 667 | tty_unlock(); | 667 | tty_unlock(tty); |
| 668 | return -EIO; | 668 | return -EIO; |
| 669 | } | 669 | } |
| 670 | 670 | ||
| @@ -707,7 +707,7 @@ enable: | |||
| 707 | if (o_work) | 707 | if (o_work) |
| 708 | schedule_work(&o_tty->buf.work); | 708 | schedule_work(&o_tty->buf.work); |
| 709 | mutex_unlock(&tty->ldisc_mutex); | 709 | mutex_unlock(&tty->ldisc_mutex); |
| 710 | tty_unlock(); | 710 | tty_unlock(tty); |
| 711 | return retval; | 711 | return retval; |
| 712 | } | 712 | } |
| 713 | 713 | ||
| @@ -815,11 +815,11 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
| 815 | * need to wait for another function taking the BTM | 815 | * need to wait for another function taking the BTM |
| 816 | */ | 816 | */ |
| 817 | clear_bit(TTY_LDISC, &tty->flags); | 817 | clear_bit(TTY_LDISC, &tty->flags); |
| 818 | tty_unlock(); | 818 | tty_unlock(tty); |
| 819 | cancel_work_sync(&tty->buf.work); | 819 | cancel_work_sync(&tty->buf.work); |
| 820 | mutex_unlock(&tty->ldisc_mutex); | 820 | mutex_unlock(&tty->ldisc_mutex); |
| 821 | retry: | 821 | retry: |
| 822 | tty_lock(); | 822 | tty_lock(tty); |
| 823 | mutex_lock(&tty->ldisc_mutex); | 823 | mutex_lock(&tty->ldisc_mutex); |
| 824 | 824 | ||
| 825 | /* At this point we have a closed ldisc and we want to | 825 | /* At this point we have a closed ldisc and we want to |
| @@ -830,7 +830,7 @@ retry: | |||
| 830 | if (atomic_read(&tty->ldisc->users) != 1) { | 830 | if (atomic_read(&tty->ldisc->users) != 1) { |
| 831 | char cur_n[TASK_COMM_LEN], tty_n[64]; | 831 | char cur_n[TASK_COMM_LEN], tty_n[64]; |
| 832 | long timeout = 3 * HZ; | 832 | long timeout = 3 * HZ; |
| 833 | tty_unlock(); | 833 | tty_unlock(tty); |
| 834 | 834 | ||
| 835 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { | 835 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { |
| 836 | timeout = MAX_SCHEDULE_TIMEOUT; | 836 | timeout = MAX_SCHEDULE_TIMEOUT; |
| @@ -911,10 +911,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
| 911 | * race with the set_ldisc code path. | 911 | * race with the set_ldisc code path. |
| 912 | */ | 912 | */ |
| 913 | 913 | ||
| 914 | tty_unlock(); | 914 | tty_unlock(tty); |
| 915 | tty_ldisc_halt(tty); | 915 | tty_ldisc_halt(tty); |
| 916 | tty_ldisc_flush_works(tty); | 916 | tty_ldisc_flush_works(tty); |
| 917 | tty_lock(); | 917 | tty_lock(tty); |
| 918 | 918 | ||
| 919 | mutex_lock(&tty->ldisc_mutex); | 919 | mutex_lock(&tty->ldisc_mutex); |
| 920 | /* | 920 | /* |
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 9ff986c32a21..69adc80c98cd 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c | |||
| @@ -4,29 +4,59 @@ | |||
| 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' | ||
| 9 | * | ||
| 10 | * This mutex is taken and released by tty_lock() and tty_unlock(), | ||
| 11 | * replacing the older big kernel lock. | ||
| 12 | * It can no longer be taken recursively, and does not get | ||
| 13 | * released implicitly while sleeping. | ||
| 14 | * | ||
| 15 | * Don't use in new code. | ||
| 16 | */ | ||
| 17 | static DEFINE_MUTEX(big_tty_mutex); | ||
| 18 | 8 | ||
| 19 | /* | 9 | /* |
| 20 | * Getting the big tty mutex. | 10 | * Getting the big tty mutex. |
| 21 | */ | 11 | */ |
| 22 | void __lockfunc tty_lock(void) | 12 | |
| 13 | void __lockfunc tty_lock(struct tty_struct *tty) | ||
| 23 | { | 14 | { |
| 24 | mutex_lock(&big_tty_mutex); | 15 | if (tty->magic != TTY_MAGIC) { |
| 16 | printk(KERN_ERR "L Bad %p\n", tty); | ||
| 17 | WARN_ON(1); | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | tty_kref_get(tty); | ||
| 21 | mutex_lock(&tty->legacy_mutex); | ||
| 25 | } | 22 | } |
| 26 | EXPORT_SYMBOL(tty_lock); | 23 | EXPORT_SYMBOL(tty_lock); |
| 27 | 24 | ||
| 28 | void __lockfunc tty_unlock(void) | 25 | void __lockfunc tty_unlock(struct tty_struct *tty) |
| 29 | { | 26 | { |
| 30 | mutex_unlock(&big_tty_mutex); | 27 | if (tty->magic != TTY_MAGIC) { |
| 28 | printk(KERN_ERR "U Bad %p\n", tty); | ||
| 29 | WARN_ON(1); | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | mutex_unlock(&tty->legacy_mutex); | ||
| 33 | tty_kref_put(tty); | ||
| 31 | } | 34 | } |
| 32 | EXPORT_SYMBOL(tty_unlock); | 35 | EXPORT_SYMBOL(tty_unlock); |
| 36 | |||
| 37 | /* | ||
| 38 | * Getting the big tty mutex for a pair of ttys with lock ordering | ||
| 39 | * On a non pty/tty pair tty2 can be NULL which is just fine. | ||
| 40 | */ | ||
| 41 | void __lockfunc tty_lock_pair(struct tty_struct *tty, | ||
| 42 | struct tty_struct *tty2) | ||
| 43 | { | ||
| 44 | if (tty < tty2) { | ||
| 45 | tty_lock(tty); | ||
| 46 | tty_lock(tty2); | ||
| 47 | } else { | ||
| 48 | if (tty2 && tty2 != tty) | ||
| 49 | tty_lock(tty2); | ||
| 50 | tty_lock(tty); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | EXPORT_SYMBOL(tty_lock_pair); | ||
| 54 | |||
| 55 | void __lockfunc tty_unlock_pair(struct tty_struct *tty, | ||
| 56 | struct tty_struct *tty2) | ||
| 57 | { | ||
| 58 | tty_unlock(tty); | ||
| 59 | if (tty2 && tty2 != tty) | ||
| 60 | tty_unlock(tty2); | ||
| 61 | } | ||
| 62 | EXPORT_SYMBOL(tty_unlock_pair); | ||
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index bf6e238146ae..d9cca95a5452 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
| @@ -230,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 230 | 230 | ||
| 231 | /* block if port is in the process of being closed */ | 231 | /* block if port is in the process of being closed */ |
| 232 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 232 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
| 233 | wait_event_interruptible_tty(port->close_wait, | 233 | wait_event_interruptible_tty(tty, port->close_wait, |
| 234 | !(port->flags & ASYNC_CLOSING)); | 234 | !(port->flags & ASYNC_CLOSING)); |
| 235 | if (port->flags & ASYNC_HUP_NOTIFY) | 235 | if (port->flags & ASYNC_HUP_NOTIFY) |
| 236 | return -EAGAIN; | 236 | return -EAGAIN; |
| @@ -296,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 296 | retval = -ERESTARTSYS; | 296 | retval = -ERESTARTSYS; |
| 297 | break; | 297 | break; |
| 298 | } | 298 | } |
| 299 | tty_unlock(); | 299 | tty_unlock(tty); |
| 300 | schedule(); | 300 | schedule(); |
| 301 | tty_lock(); | 301 | tty_lock(tty); |
| 302 | } | 302 | } |
| 303 | finish_wait(&port->open_wait, &wait); | 303 | finish_wait(&port->open_wait, &wait); |
| 304 | 304 | ||
diff --git a/include/linux/tty.h b/include/linux/tty.h index 9f47ab540f65..4990ef2b1fb7 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 */ |
| @@ -605,8 +606,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty, | |||
| 605 | 606 | ||
| 606 | /* tty_mutex.c */ | 607 | /* tty_mutex.c */ |
| 607 | /* functions for preparation of BKL removal */ | 608 | /* functions for preparation of BKL removal */ |
| 608 | extern void __lockfunc tty_lock(void) __acquires(tty_lock); | 609 | extern void __lockfunc tty_lock(struct tty_struct *tty); |
| 609 | extern void __lockfunc tty_unlock(void) __releases(tty_lock); | 610 | extern void __lockfunc tty_unlock(struct tty_struct *tty); |
| 611 | extern void __lockfunc tty_lock_pair(struct tty_struct *tty, | ||
| 612 | struct tty_struct *tty2); | ||
| 613 | extern void __lockfunc tty_unlock_pair(struct tty_struct *tty, | ||
| 614 | struct tty_struct *tty2); | ||
| 610 | 615 | ||
| 611 | /* | 616 | /* |
| 612 | * this shall be called only from where BTM is held (like close) | 617 | * this shall be called only from where BTM is held (like close) |
| @@ -621,9 +626,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock); | |||
| 621 | static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, | 626 | static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, |
| 622 | long timeout) | 627 | long timeout) |
| 623 | { | 628 | { |
| 624 | tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ | 629 | tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */ |
| 625 | tty_wait_until_sent(tty, timeout); | 630 | tty_wait_until_sent(tty, timeout); |
| 626 | tty_lock(); | 631 | tty_lock(tty); |
| 627 | } | 632 | } |
| 628 | 633 | ||
| 629 | /* | 634 | /* |
| @@ -638,16 +643,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, | |||
| 638 | * | 643 | * |
| 639 | * Do not use in new code. | 644 | * Do not use in new code. |
| 640 | */ | 645 | */ |
| 641 | #define wait_event_interruptible_tty(wq, condition) \ | 646 | #define wait_event_interruptible_tty(tty, wq, condition) \ |
| 642 | ({ \ | 647 | ({ \ |
| 643 | int __ret = 0; \ | 648 | int __ret = 0; \ |
| 644 | if (!(condition)) { \ | 649 | if (!(condition)) { \ |
| 645 | __wait_event_interruptible_tty(wq, condition, __ret); \ | 650 | __wait_event_interruptible_tty(tty, wq, condition, __ret); \ |
| 646 | } \ | 651 | } \ |
| 647 | __ret; \ | 652 | __ret; \ |
| 648 | }) | 653 | }) |
| 649 | 654 | ||
| 650 | #define __wait_event_interruptible_tty(wq, condition, ret) \ | 655 | #define __wait_event_interruptible_tty(tty, wq, condition, ret) \ |
| 651 | do { \ | 656 | do { \ |
| 652 | DEFINE_WAIT(__wait); \ | 657 | DEFINE_WAIT(__wait); \ |
| 653 | \ | 658 | \ |
| @@ -656,9 +661,9 @@ do { \ | |||
| 656 | if (condition) \ | 661 | if (condition) \ |
| 657 | break; \ | 662 | break; \ |
| 658 | if (!signal_pending(current)) { \ | 663 | if (!signal_pending(current)) { \ |
| 659 | tty_unlock(); \ | 664 | tty_unlock(tty); \ |
| 660 | schedule(); \ | 665 | schedule(); \ |
| 661 | tty_lock(); \ | 666 | tty_lock(tty); \ |
| 662 | continue; \ | 667 | continue; \ |
| 663 | } \ | 668 | } \ |
| 664 | ret = -ERESTARTSYS; \ | 669 | ret = -ERESTARTSYS; \ |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index d1820ff14aee..aa5d73b786ac 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
| @@ -710,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 710 | break; | 710 | break; |
| 711 | } | 711 | } |
| 712 | 712 | ||
| 713 | tty_unlock(); | 713 | tty_unlock(tty); |
| 714 | schedule(); | 714 | schedule(); |
| 715 | tty_lock(); | 715 | tty_lock(tty); |
| 716 | } | 716 | } |
| 717 | set_current_state(TASK_RUNNING); | 717 | set_current_state(TASK_RUNNING); |
| 718 | remove_wait_queue(&dev->wait, &wait); | 718 | remove_wait_queue(&dev->wait, &wait); |
