Skip to content

Commit

Permalink
n_tty: Replace canon_data with index comparison
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Peter Hurley authored and Greg Kroah-Hartman committed Jul 23, 2013
1 parent 9356b53 commit a73d3d6
Showing 1 changed file with 6 additions and 16 deletions.
22 changes: 6 additions & 16 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ struct n_tty_data {
unsigned int echo_pos;
unsigned int echo_cnt;

int canon_data;
size_t canon_head;
unsigned int canon_column;

Expand Down Expand Up @@ -158,7 +157,7 @@ static int receive_room(struct tty_struct *tty)
* characters will be beeped.
*/
if (left <= 0)
left = ldata->icanon && !ldata->canon_data;
left = ldata->icanon && ldata->canon_head == ldata->read_tail;

return left;
}
Expand Down Expand Up @@ -237,14 +236,14 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
unsigned long flags;

raw_spin_lock_irqsave(&ldata->read_lock, flags);
ldata->read_head = ldata->read_tail = 0;
ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
raw_spin_unlock_irqrestore(&ldata->read_lock, flags);

mutex_lock(&ldata->echo_lock);
ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
mutex_unlock(&ldata->echo_lock);

ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
ldata->erasing = 0;
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
}

Expand Down Expand Up @@ -1360,7 +1359,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags);
put_tty_queue_nolock(c, ldata);
ldata->canon_head = ldata->read_head;
ldata->canon_data++;
raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
Expand Down Expand Up @@ -1562,7 +1560,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
if (canon_change) {
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
ldata->canon_head = ldata->read_tail;
ldata->canon_data = 0;
ldata->erasing = 0;
}

Expand Down Expand Up @@ -1713,7 +1710,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)

tty_flush_to_ldisc(tty);
if (ldata->icanon && !L_EXTPROC(tty)) {
if (ldata->canon_data)
if (ldata->canon_head != ldata->read_tail)
return 1;
} else if (read_cnt(ldata) >= (amt ? amt : 1))
return 1;
Expand Down Expand Up @@ -1850,15 +1847,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,

raw_spin_lock_irqsave(&ldata->read_lock, flags);
ldata->read_tail += c;
if (found) {
if (found)
__clear_bit(eol, ldata->read_flags);
/* this test should be redundant:
* we shouldn't be reading data if
* canon_data is 0
*/
if (--ldata->canon_data < 0)
ldata->canon_data = 0;
}
raw_spin_unlock_irqrestore(&ldata->read_lock, flags);

if (found)
Expand Down Expand Up @@ -2264,7 +2254,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata)
{
size_t nr, head, tail;

if (!ldata->canon_data)
if (ldata->canon_head == ldata->read_tail)
return 0;
head = ldata->canon_head;
tail = ldata->read_tail;
Expand Down

0 comments on commit a73d3d6

Please sign in to comment.