aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2013-06-15 09:14:25 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-23 19:43:01 -0400
commita73d3d6987e4e60d442b7cdf4f7c38400b454bf5 (patch)
treef6bc7f43c964c3d045c104de054de5b0b83bacdf
parent9356b535fcb71db494fc434acceb79f56d15bda2 (diff)
n_tty: Replace canon_data with index comparison
canon_data represented the # of lines which had been copied to the receive buffer but not yet copied to the user buffer. The value was tested to determine if input was available in canonical mode (and also to force input overrun if the receive buffer was full but a newline had not been received). However, the actual count was irrelevent; only whether it was non-zero (meaning 'is there any input to transfer?'). This shared count is unnecessary and unsafe with a lockless algorithm. The same check is made by comparing canon_head with read_tail instead. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/n_tty.c22
1 files changed, 6 insertions, 16 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 0599b583d21e..1098dd73a4f7 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -104,7 +104,6 @@ struct n_tty_data {
104 unsigned int echo_pos; 104 unsigned int echo_pos;
105 unsigned int echo_cnt; 105 unsigned int echo_cnt;
106 106
107 int canon_data;
108 size_t canon_head; 107 size_t canon_head;
109 unsigned int canon_column; 108 unsigned int canon_column;
110 109
@@ -158,7 +157,7 @@ static int receive_room(struct tty_struct *tty)
158 * characters will be beeped. 157 * characters will be beeped.
159 */ 158 */
160 if (left <= 0) 159 if (left <= 0)
161 left = ldata->icanon && !ldata->canon_data; 160 left = ldata->icanon && ldata->canon_head == ldata->read_tail;
162 161
163 return left; 162 return left;
164} 163}
@@ -237,14 +236,14 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
237 unsigned long flags; 236 unsigned long flags;
238 237
239 raw_spin_lock_irqsave(&ldata->read_lock, flags); 238 raw_spin_lock_irqsave(&ldata->read_lock, flags);
240 ldata->read_head = ldata->read_tail = 0; 239 ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
241 raw_spin_unlock_irqrestore(&ldata->read_lock, flags); 240 raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
242 241
243 mutex_lock(&ldata->echo_lock); 242 mutex_lock(&ldata->echo_lock);
244 ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0; 243 ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
245 mutex_unlock(&ldata->echo_lock); 244 mutex_unlock(&ldata->echo_lock);
246 245
247 ldata->canon_head = ldata->canon_data = ldata->erasing = 0; 246 ldata->erasing = 0;
248 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); 247 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
249} 248}
250 249
@@ -1360,7 +1359,6 @@ handle_newline:
1360 set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags); 1359 set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags);
1361 put_tty_queue_nolock(c, ldata); 1360 put_tty_queue_nolock(c, ldata);
1362 ldata->canon_head = ldata->read_head; 1361 ldata->canon_head = ldata->read_head;
1363 ldata->canon_data++;
1364 raw_spin_unlock_irqrestore(&ldata->read_lock, flags); 1362 raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
1365 kill_fasync(&tty->fasync, SIGIO, POLL_IN); 1363 kill_fasync(&tty->fasync, SIGIO, POLL_IN);
1366 if (waitqueue_active(&tty->read_wait)) 1364 if (waitqueue_active(&tty->read_wait))
@@ -1562,7 +1560,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
1562 if (canon_change) { 1560 if (canon_change) {
1563 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); 1561 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
1564 ldata->canon_head = ldata->read_tail; 1562 ldata->canon_head = ldata->read_tail;
1565 ldata->canon_data = 0;
1566 ldata->erasing = 0; 1563 ldata->erasing = 0;
1567 } 1564 }
1568 1565
@@ -1713,7 +1710,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
1713 1710
1714 tty_flush_to_ldisc(tty); 1711 tty_flush_to_ldisc(tty);
1715 if (ldata->icanon && !L_EXTPROC(tty)) { 1712 if (ldata->icanon && !L_EXTPROC(tty)) {
1716 if (ldata->canon_data) 1713 if (ldata->canon_head != ldata->read_tail)
1717 return 1; 1714 return 1;
1718 } else if (read_cnt(ldata) >= (amt ? amt : 1)) 1715 } else if (read_cnt(ldata) >= (amt ? amt : 1))
1719 return 1; 1716 return 1;
@@ -1850,15 +1847,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
1850 1847
1851 raw_spin_lock_irqsave(&ldata->read_lock, flags); 1848 raw_spin_lock_irqsave(&ldata->read_lock, flags);
1852 ldata->read_tail += c; 1849 ldata->read_tail += c;
1853 if (found) { 1850 if (found)
1854 __clear_bit(eol, ldata->read_flags); 1851 __clear_bit(eol, ldata->read_flags);
1855 /* this test should be redundant:
1856 * we shouldn't be reading data if
1857 * canon_data is 0
1858 */
1859 if (--ldata->canon_data < 0)
1860 ldata->canon_data = 0;
1861 }
1862 raw_spin_unlock_irqrestore(&ldata->read_lock, flags); 1852 raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
1863 1853
1864 if (found) 1854 if (found)
@@ -2264,7 +2254,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata)
2264{ 2254{
2265 size_t nr, head, tail; 2255 size_t nr, head, tail;
2266 2256
2267 if (!ldata->canon_data) 2257 if (ldata->canon_head == ldata->read_tail)
2268 return 0; 2258 return 0;
2269 head = ldata->canon_head; 2259 head = ldata->canon_head;
2270 tail = ldata->read_tail; 2260 tail = ldata->read_tail;