--- drivers/tty/n_tty.c-old 2014-10-16 16:39:35.909350338 -0400 +++ drivers/tty/n_tty.c 2014-10-16 16:49:00.004930469 -0400 @@ -124,6 +124,7 @@ struct mutex atomic_read_lock; struct mutex output_lock; + struct mutex read_buf_lock; }; static inline size_t read_cnt(struct n_tty_data *ldata) @@ -1686,9 +1687,11 @@ char *fp, int count) { int room, n; + struct n_tty_data *ldata = tty->disc_data; down_read(&tty->termios_rwsem); + mutex_lock(&ldata->read_buf_lock); while (1) { room = receive_room(tty); n = min(count, room); @@ -1703,6 +1706,7 @@ tty->receive_room = room; n_tty_check_throttle(tty); + mutex_unlock(&ldata->read_buf_lock); up_read(&tty->termios_rwsem); } @@ -1713,7 +1717,7 @@ int room, n, rcvd = 0; down_read(&tty->termios_rwsem); - + mutex_lock(&ldata->read_buf_lock); while (1) { room = receive_room(tty); n = min(count, room); @@ -1732,6 +1736,7 @@ tty->receive_room = room; n_tty_check_throttle(tty); + mutex_unlock(&ldata->read_buf_lock); up_read(&tty->termios_rwsem); return rcvd; @@ -1880,6 +1885,7 @@ ldata->overrun_time = jiffies; mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); + mutex_init(&ldata->read_buf_lock); tty->disc_data = ldata; reset_buffer_flags(tty->disc_data); @@ -1945,6 +1951,8 @@ size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); retval = 0; + + mutex_lock(&ldata->read_buf_lock); n = min(read_cnt(ldata), N_TTY_BUF_SIZE - tail); n = min(*nr, n); if (n) { @@ -1960,6 +1968,7 @@ *b += n; *nr -= n; } + mutex_unlock(&ldata->read_buf_lock); return retval; } @@ -1990,6 +1999,8 @@ size_t tail; int ret, found = 0; bool eof_push = 0; + + mutex_lock(&ldata->read_buf_lock); /* N.B. avoid overrun if nr == 0 */ n = min(*nr, read_cnt(ldata)); @@ -2049,6 +2060,8 @@ ldata->line_start = ldata->read_tail; tty_audit_push(tty); } + + mutex_unlock(&ldata->read_buf_lock); return eof_push ? -EAGAIN : 0; }