| .. | .. |
|---|
| 50 | 50 | #include <linux/ratelimit.h> |
|---|
| 51 | 51 | #include <linux/vmalloc.h> |
|---|
| 52 | 52 | |
|---|
| 53 | | - |
|---|
| 54 | | -/* number of characters left in xmit buffer before select has we have room */ |
|---|
| 53 | +/* |
|---|
| 54 | + * Until this number of characters is queued in the xmit buffer, select will |
|---|
| 55 | + * return "we have room for writes". |
|---|
| 56 | + */ |
|---|
| 55 | 57 | #define WAKEUP_CHARS 256 |
|---|
| 56 | 58 | |
|---|
| 57 | 59 | /* |
|---|
| .. | .. |
|---|
| 82 | 84 | #ifdef N_TTY_TRACE |
|---|
| 83 | 85 | # define n_tty_trace(f, args...) trace_printk(f, ##args) |
|---|
| 84 | 86 | #else |
|---|
| 85 | | -# define n_tty_trace(f, args...) |
|---|
| 87 | +# define n_tty_trace(f, args...) no_printk(f, ##args) |
|---|
| 86 | 88 | #endif |
|---|
| 87 | 89 | |
|---|
| 88 | 90 | struct n_tty_data { |
|---|
| .. | .. |
|---|
| 162 | 164 | memset(buffer, 0x00, size); |
|---|
| 163 | 165 | } |
|---|
| 164 | 166 | |
|---|
| 165 | | -static int tty_copy_to_user(struct tty_struct *tty, void __user *to, |
|---|
| 166 | | - size_t tail, size_t n) |
|---|
| 167 | +static void tty_copy(struct tty_struct *tty, void *to, size_t tail, size_t n) |
|---|
| 167 | 168 | { |
|---|
| 168 | 169 | struct n_tty_data *ldata = tty->disc_data; |
|---|
| 169 | 170 | size_t size = N_TTY_BUF_SIZE - tail; |
|---|
| 170 | 171 | void *from = read_buf_addr(ldata, tail); |
|---|
| 171 | | - int uncopied; |
|---|
| 172 | 172 | |
|---|
| 173 | 173 | if (n > size) { |
|---|
| 174 | 174 | tty_audit_add_data(tty, from, size); |
|---|
| 175 | | - uncopied = copy_to_user(to, from, size); |
|---|
| 176 | | - zero_buffer(tty, from, size - uncopied); |
|---|
| 177 | | - if (uncopied) |
|---|
| 178 | | - return uncopied; |
|---|
| 175 | + memcpy(to, from, size); |
|---|
| 176 | + zero_buffer(tty, from, size); |
|---|
| 179 | 177 | to += size; |
|---|
| 180 | 178 | n -= size; |
|---|
| 181 | 179 | from = ldata->read_buf; |
|---|
| 182 | 180 | } |
|---|
| 183 | 181 | |
|---|
| 184 | 182 | tty_audit_add_data(tty, from, n); |
|---|
| 185 | | - uncopied = copy_to_user(to, from, n); |
|---|
| 186 | | - zero_buffer(tty, from, n - uncopied); |
|---|
| 187 | | - return uncopied; |
|---|
| 183 | + memcpy(to, from, n); |
|---|
| 184 | + zero_buffer(tty, from, n); |
|---|
| 188 | 185 | } |
|---|
| 189 | 186 | |
|---|
| 190 | 187 | /** |
|---|
| .. | .. |
|---|
| 320 | 317 | |
|---|
| 321 | 318 | /** |
|---|
| 322 | 319 | * reset_buffer_flags - reset buffer state |
|---|
| 323 | | - * @tty: terminal to reset |
|---|
| 320 | + * @ldata: line disc data to reset |
|---|
| 324 | 321 | * |
|---|
| 325 | 322 | * Reset the read buffer counters and clear the flags. |
|---|
| 326 | 323 | * Called from n_tty_open() and n_tty_flush_buffer(). |
|---|
| .. | .. |
|---|
| 548 | 545 | mutex_lock(&ldata->output_lock); |
|---|
| 549 | 546 | |
|---|
| 550 | 547 | space = tty_write_room(tty); |
|---|
| 551 | | - if (!space) { |
|---|
| 548 | + if (space <= 0) { |
|---|
| 552 | 549 | mutex_unlock(&ldata->output_lock); |
|---|
| 553 | | - return 0; |
|---|
| 550 | + return space; |
|---|
| 554 | 551 | } |
|---|
| 555 | 552 | if (nr > space) |
|---|
| 556 | 553 | nr = space; |
|---|
| .. | .. |
|---|
| 652 | 649 | op = echo_buf(ldata, tail + 1); |
|---|
| 653 | 650 | |
|---|
| 654 | 651 | switch (op) { |
|---|
| 652 | + case ECHO_OP_ERASE_TAB: { |
|---|
| 655 | 653 | unsigned int num_chars, num_bs; |
|---|
| 656 | 654 | |
|---|
| 657 | | - case ECHO_OP_ERASE_TAB: |
|---|
| 658 | 655 | if (MASK(ldata->echo_commit) == MASK(tail + 2)) |
|---|
| 659 | 656 | goto not_yet_stored; |
|---|
| 660 | 657 | num_chars = echo_buf(ldata, tail + 2); |
|---|
| .. | .. |
|---|
| 685 | 682 | } |
|---|
| 686 | 683 | tail += 3; |
|---|
| 687 | 684 | break; |
|---|
| 688 | | - |
|---|
| 685 | + } |
|---|
| 689 | 686 | case ECHO_OP_SET_CANON_COL: |
|---|
| 690 | 687 | ldata->canon_column = ldata->column; |
|---|
| 691 | 688 | tail += 2; |
|---|
| .. | .. |
|---|
| 904 | 901 | /** |
|---|
| 905 | 902 | * echo_char_raw - echo a character raw |
|---|
| 906 | 903 | * @c: unicode byte to echo |
|---|
| 907 | | - * @tty: terminal device |
|---|
| 904 | + * @ldata: line disc data |
|---|
| 908 | 905 | * |
|---|
| 909 | 906 | * Echo user input back onto the screen. This must be called only when |
|---|
| 910 | 907 | * L_ECHO(tty) is true. Called from the driver receive_buf path. |
|---|
| .. | .. |
|---|
| 1940 | 1937 | /** |
|---|
| 1941 | 1938 | * copy_from_read_buf - copy read data directly |
|---|
| 1942 | 1939 | * @tty: terminal device |
|---|
| 1943 | | - * @b: user data |
|---|
| 1940 | + * @kbp: data |
|---|
| 1944 | 1941 | * @nr: size of data |
|---|
| 1945 | 1942 | * |
|---|
| 1946 | 1943 | * Helper function to speed up n_tty_read. It is only called when |
|---|
| 1947 | | - * ICANON is off; it copies characters straight from the tty queue to |
|---|
| 1948 | | - * user space directly. It can be profitably called twice; once to |
|---|
| 1949 | | - * drain the space from the tail pointer to the (physical) end of the |
|---|
| 1950 | | - * buffer, and once to drain the space from the (physical) beginning of |
|---|
| 1951 | | - * the buffer to head pointer. |
|---|
| 1944 | + * ICANON is off; it copies characters straight from the tty queue. |
|---|
| 1952 | 1945 | * |
|---|
| 1953 | 1946 | * Called under the ldata->atomic_read_lock sem |
|---|
| 1947 | + * |
|---|
| 1948 | + * Returns true if it successfully copied data, but there is still |
|---|
| 1949 | + * more data to be had. |
|---|
| 1954 | 1950 | * |
|---|
| 1955 | 1951 | * n_tty_read()/consumer path: |
|---|
| 1956 | 1952 | * caller holds non-exclusive termios_rwsem |
|---|
| 1957 | 1953 | * read_tail published |
|---|
| 1958 | 1954 | */ |
|---|
| 1959 | 1955 | |
|---|
| 1960 | | -static int copy_from_read_buf(struct tty_struct *tty, |
|---|
| 1961 | | - unsigned char __user **b, |
|---|
| 1956 | +static bool copy_from_read_buf(struct tty_struct *tty, |
|---|
| 1957 | + unsigned char **kbp, |
|---|
| 1962 | 1958 | size_t *nr) |
|---|
| 1963 | 1959 | |
|---|
| 1964 | 1960 | { |
|---|
| 1965 | 1961 | struct n_tty_data *ldata = tty->disc_data; |
|---|
| 1966 | | - int retval; |
|---|
| 1967 | 1962 | size_t n; |
|---|
| 1968 | 1963 | bool is_eof; |
|---|
| 1969 | 1964 | size_t head = smp_load_acquire(&ldata->commit_head); |
|---|
| 1970 | 1965 | size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); |
|---|
| 1971 | 1966 | |
|---|
| 1972 | | - retval = 0; |
|---|
| 1973 | 1967 | n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); |
|---|
| 1974 | 1968 | n = min(*nr, n); |
|---|
| 1975 | 1969 | if (n) { |
|---|
| 1976 | 1970 | unsigned char *from = read_buf_addr(ldata, tail); |
|---|
| 1977 | | - retval = copy_to_user(*b, from, n); |
|---|
| 1978 | | - n -= retval; |
|---|
| 1971 | + memcpy(*kbp, from, n); |
|---|
| 1979 | 1972 | is_eof = n == 1 && *from == EOF_CHAR(tty); |
|---|
| 1980 | 1973 | tty_audit_add_data(tty, from, n); |
|---|
| 1981 | 1974 | zero_buffer(tty, from, n); |
|---|
| .. | .. |
|---|
| 1983 | 1976 | /* Turn single EOF into zero-length read */ |
|---|
| 1984 | 1977 | if (L_EXTPROC(tty) && ldata->icanon && is_eof && |
|---|
| 1985 | 1978 | (head == ldata->read_tail)) |
|---|
| 1986 | | - n = 0; |
|---|
| 1987 | | - *b += n; |
|---|
| 1979 | + return false; |
|---|
| 1980 | + *kbp += n; |
|---|
| 1988 | 1981 | *nr -= n; |
|---|
| 1982 | + |
|---|
| 1983 | + /* If we have more to copy, let the caller know */ |
|---|
| 1984 | + return head != ldata->read_tail; |
|---|
| 1989 | 1985 | } |
|---|
| 1990 | | - return retval; |
|---|
| 1986 | + return false; |
|---|
| 1991 | 1987 | } |
|---|
| 1992 | 1988 | |
|---|
| 1993 | 1989 | /** |
|---|
| 1994 | 1990 | * canon_copy_from_read_buf - copy read data in canonical mode |
|---|
| 1995 | 1991 | * @tty: terminal device |
|---|
| 1996 | | - * @b: user data |
|---|
| 1992 | + * @kbp: data |
|---|
| 1997 | 1993 | * @nr: size of data |
|---|
| 1998 | 1994 | * |
|---|
| 1999 | 1995 | * Helper function for n_tty_read. It is only called when ICANON is on; |
|---|
| 2000 | 1996 | * it copies one line of input up to and including the line-delimiting |
|---|
| 2001 | | - * character into the user-space buffer. |
|---|
| 1997 | + * character into the result buffer. |
|---|
| 2002 | 1998 | * |
|---|
| 2003 | 1999 | * NB: When termios is changed from non-canonical to canonical mode and |
|---|
| 2004 | 2000 | * the read buffer contains data, n_tty_set_termios() simulates an EOF |
|---|
| .. | .. |
|---|
| 2013 | 2009 | * read_tail published |
|---|
| 2014 | 2010 | */ |
|---|
| 2015 | 2011 | |
|---|
| 2016 | | -static int canon_copy_from_read_buf(struct tty_struct *tty, |
|---|
| 2017 | | - unsigned char __user **b, |
|---|
| 2018 | | - size_t *nr) |
|---|
| 2012 | +static bool canon_copy_from_read_buf(struct tty_struct *tty, |
|---|
| 2013 | + unsigned char **kbp, |
|---|
| 2014 | + size_t *nr) |
|---|
| 2019 | 2015 | { |
|---|
| 2020 | 2016 | struct n_tty_data *ldata = tty->disc_data; |
|---|
| 2021 | 2017 | size_t n, size, more, c; |
|---|
| 2022 | 2018 | size_t eol; |
|---|
| 2023 | | - size_t tail; |
|---|
| 2024 | | - int ret, found = 0; |
|---|
| 2019 | + size_t tail, canon_head; |
|---|
| 2020 | + int found = 0; |
|---|
| 2025 | 2021 | |
|---|
| 2026 | 2022 | /* N.B. avoid overrun if nr == 0 */ |
|---|
| 2027 | 2023 | if (!*nr) |
|---|
| 2028 | | - return 0; |
|---|
| 2024 | + return false; |
|---|
| 2029 | 2025 | |
|---|
| 2030 | | - n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail); |
|---|
| 2026 | + canon_head = smp_load_acquire(&ldata->canon_head); |
|---|
| 2027 | + n = min(*nr, canon_head - ldata->read_tail); |
|---|
| 2031 | 2028 | |
|---|
| 2032 | 2029 | tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); |
|---|
| 2033 | 2030 | size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); |
|---|
| .. | .. |
|---|
| 2049 | 2046 | n += N_TTY_BUF_SIZE; |
|---|
| 2050 | 2047 | c = n + found; |
|---|
| 2051 | 2048 | |
|---|
| 2052 | | - if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) { |
|---|
| 2053 | | - c = min(*nr, c); |
|---|
| 2049 | + if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) |
|---|
| 2054 | 2050 | n = c; |
|---|
| 2055 | | - } |
|---|
| 2056 | 2051 | |
|---|
| 2057 | 2052 | n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", |
|---|
| 2058 | 2053 | __func__, eol, found, n, c, tail, more); |
|---|
| 2059 | 2054 | |
|---|
| 2060 | | - ret = tty_copy_to_user(tty, *b, tail, n); |
|---|
| 2061 | | - if (ret) |
|---|
| 2062 | | - return -EFAULT; |
|---|
| 2063 | | - *b += n; |
|---|
| 2055 | + tty_copy(tty, *kbp, tail, n); |
|---|
| 2056 | + *kbp += n; |
|---|
| 2064 | 2057 | *nr -= n; |
|---|
| 2065 | 2058 | |
|---|
| 2066 | 2059 | if (found) |
|---|
| .. | .. |
|---|
| 2073 | 2066 | else |
|---|
| 2074 | 2067 | ldata->push = 0; |
|---|
| 2075 | 2068 | tty_audit_push(); |
|---|
| 2069 | + return false; |
|---|
| 2076 | 2070 | } |
|---|
| 2077 | | - return 0; |
|---|
| 2071 | + |
|---|
| 2072 | + /* No EOL found - do a continuation retry if there is more data */ |
|---|
| 2073 | + return ldata->read_tail != canon_head; |
|---|
| 2078 | 2074 | } |
|---|
| 2079 | 2075 | |
|---|
| 2080 | | -extern ssize_t redirected_tty_write(struct file *, const char __user *, |
|---|
| 2081 | | - size_t, loff_t *); |
|---|
| 2076 | +/* |
|---|
| 2077 | + * If we finished a read at the exact location of an |
|---|
| 2078 | + * EOF (special EOL character that's a __DISABLED_CHAR) |
|---|
| 2079 | + * in the stream, silently eat the EOF. |
|---|
| 2080 | + */ |
|---|
| 2081 | +static void canon_skip_eof(struct tty_struct *tty) |
|---|
| 2082 | +{ |
|---|
| 2083 | + struct n_tty_data *ldata = tty->disc_data; |
|---|
| 2084 | + size_t tail, canon_head; |
|---|
| 2085 | + |
|---|
| 2086 | + canon_head = smp_load_acquire(&ldata->canon_head); |
|---|
| 2087 | + tail = ldata->read_tail; |
|---|
| 2088 | + |
|---|
| 2089 | + // No data? |
|---|
| 2090 | + if (tail == canon_head) |
|---|
| 2091 | + return; |
|---|
| 2092 | + |
|---|
| 2093 | + // See if the tail position is EOF in the circular buffer |
|---|
| 2094 | + tail &= (N_TTY_BUF_SIZE - 1); |
|---|
| 2095 | + if (!test_bit(tail, ldata->read_flags)) |
|---|
| 2096 | + return; |
|---|
| 2097 | + if (read_buf(ldata, tail) != __DISABLED_CHAR) |
|---|
| 2098 | + return; |
|---|
| 2099 | + |
|---|
| 2100 | + // Clear the EOL bit, skip the EOF char. |
|---|
| 2101 | + clear_bit(tail, ldata->read_flags); |
|---|
| 2102 | + smp_store_release(&ldata->read_tail, ldata->read_tail + 1); |
|---|
| 2103 | +} |
|---|
| 2082 | 2104 | |
|---|
| 2083 | 2105 | /** |
|---|
| 2084 | 2106 | * job_control - check job control |
|---|
| .. | .. |
|---|
| 2101 | 2123 | /* NOTE: not yet done after every sleep pending a thorough |
|---|
| 2102 | 2124 | check of the logic of this change. -- jlc */ |
|---|
| 2103 | 2125 | /* don't stop on /dev/console */ |
|---|
| 2104 | | - if (file->f_op->write == redirected_tty_write) |
|---|
| 2126 | + if (file->f_op->write_iter == redirected_tty_write) |
|---|
| 2105 | 2127 | return 0; |
|---|
| 2106 | 2128 | |
|---|
| 2107 | 2129 | return __tty_check_change(tty, SIGTTIN); |
|---|
| .. | .. |
|---|
| 2128 | 2150 | */ |
|---|
| 2129 | 2151 | |
|---|
| 2130 | 2152 | static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, |
|---|
| 2131 | | - unsigned char __user *buf, size_t nr) |
|---|
| 2153 | + unsigned char *kbuf, size_t nr, |
|---|
| 2154 | + void **cookie, unsigned long offset) |
|---|
| 2132 | 2155 | { |
|---|
| 2133 | 2156 | struct n_tty_data *ldata = tty->disc_data; |
|---|
| 2134 | | - unsigned char __user *b = buf; |
|---|
| 2157 | + unsigned char *kb = kbuf; |
|---|
| 2135 | 2158 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
|---|
| 2136 | 2159 | int c; |
|---|
| 2137 | 2160 | int minimum, time; |
|---|
| .. | .. |
|---|
| 2139 | 2162 | long timeout; |
|---|
| 2140 | 2163 | int packet; |
|---|
| 2141 | 2164 | size_t tail; |
|---|
| 2165 | + |
|---|
| 2166 | + /* |
|---|
| 2167 | + * Is this a continuation of a read started earler? |
|---|
| 2168 | + * |
|---|
| 2169 | + * If so, we still hold the atomic_read_lock and the |
|---|
| 2170 | + * termios_rwsem, and can just continue to copy data. |
|---|
| 2171 | + */ |
|---|
| 2172 | + if (*cookie) { |
|---|
| 2173 | + if (ldata->icanon && !L_EXTPROC(tty)) { |
|---|
| 2174 | + /* |
|---|
| 2175 | + * If we have filled the user buffer, see |
|---|
| 2176 | + * if we should skip an EOF character before |
|---|
| 2177 | + * releasing the lock and returning done. |
|---|
| 2178 | + */ |
|---|
| 2179 | + if (!nr) |
|---|
| 2180 | + canon_skip_eof(tty); |
|---|
| 2181 | + else if (canon_copy_from_read_buf(tty, &kb, &nr)) |
|---|
| 2182 | + return kb - kbuf; |
|---|
| 2183 | + } else { |
|---|
| 2184 | + if (copy_from_read_buf(tty, &kb, &nr)) |
|---|
| 2185 | + return kb - kbuf; |
|---|
| 2186 | + } |
|---|
| 2187 | + |
|---|
| 2188 | + /* No more data - release locks and stop retries */ |
|---|
| 2189 | + n_tty_kick_worker(tty); |
|---|
| 2190 | + n_tty_check_unthrottle(tty); |
|---|
| 2191 | + up_read(&tty->termios_rwsem); |
|---|
| 2192 | + mutex_unlock(&ldata->atomic_read_lock); |
|---|
| 2193 | + *cookie = NULL; |
|---|
| 2194 | + return kb - kbuf; |
|---|
| 2195 | + } |
|---|
| 2142 | 2196 | |
|---|
| 2143 | 2197 | c = job_control(tty, file); |
|---|
| 2144 | 2198 | if (c < 0) |
|---|
| .. | .. |
|---|
| 2177 | 2231 | /* First test for status change. */ |
|---|
| 2178 | 2232 | if (packet && tty->link->ctrl_status) { |
|---|
| 2179 | 2233 | unsigned char cs; |
|---|
| 2180 | | - if (b != buf) |
|---|
| 2234 | + if (kb != kbuf) |
|---|
| 2181 | 2235 | break; |
|---|
| 2182 | 2236 | spin_lock_irq(&tty->link->ctrl_lock); |
|---|
| 2183 | 2237 | cs = tty->link->ctrl_status; |
|---|
| 2184 | 2238 | tty->link->ctrl_status = 0; |
|---|
| 2185 | 2239 | spin_unlock_irq(&tty->link->ctrl_lock); |
|---|
| 2186 | | - if (put_user(cs, b)) { |
|---|
| 2187 | | - retval = -EFAULT; |
|---|
| 2188 | | - break; |
|---|
| 2189 | | - } |
|---|
| 2190 | | - b++; |
|---|
| 2240 | + *kb++ = cs; |
|---|
| 2191 | 2241 | nr--; |
|---|
| 2192 | 2242 | break; |
|---|
| 2193 | 2243 | } |
|---|
| .. | .. |
|---|
| 2230 | 2280 | } |
|---|
| 2231 | 2281 | |
|---|
| 2232 | 2282 | if (ldata->icanon && !L_EXTPROC(tty)) { |
|---|
| 2233 | | - retval = canon_copy_from_read_buf(tty, &b, &nr); |
|---|
| 2234 | | - if (retval) |
|---|
| 2235 | | - break; |
|---|
| 2283 | + if (canon_copy_from_read_buf(tty, &kb, &nr)) |
|---|
| 2284 | + goto more_to_be_read; |
|---|
| 2236 | 2285 | } else { |
|---|
| 2237 | | - int uncopied; |
|---|
| 2238 | | - |
|---|
| 2239 | 2286 | /* Deal with packet mode. */ |
|---|
| 2240 | | - if (packet && b == buf) { |
|---|
| 2241 | | - if (put_user(TIOCPKT_DATA, b)) { |
|---|
| 2242 | | - retval = -EFAULT; |
|---|
| 2243 | | - break; |
|---|
| 2244 | | - } |
|---|
| 2245 | | - b++; |
|---|
| 2287 | + if (packet && kb == kbuf) { |
|---|
| 2288 | + *kb++ = TIOCPKT_DATA; |
|---|
| 2246 | 2289 | nr--; |
|---|
| 2247 | 2290 | } |
|---|
| 2248 | 2291 | |
|---|
| 2249 | | - uncopied = copy_from_read_buf(tty, &b, &nr); |
|---|
| 2250 | | - uncopied += copy_from_read_buf(tty, &b, &nr); |
|---|
| 2251 | | - if (uncopied) { |
|---|
| 2252 | | - retval = -EFAULT; |
|---|
| 2253 | | - break; |
|---|
| 2292 | + /* |
|---|
| 2293 | + * Copy data, and if there is more to be had |
|---|
| 2294 | + * and we have nothing more to wait for, then |
|---|
| 2295 | + * let's mark us for retries. |
|---|
| 2296 | + * |
|---|
| 2297 | + * NOTE! We return here with both the termios_sem |
|---|
| 2298 | + * and atomic_read_lock still held, the retries |
|---|
| 2299 | + * will release them when done. |
|---|
| 2300 | + */ |
|---|
| 2301 | + if (copy_from_read_buf(tty, &kb, &nr) && kb - kbuf >= minimum) { |
|---|
| 2302 | +more_to_be_read: |
|---|
| 2303 | + remove_wait_queue(&tty->read_wait, &wait); |
|---|
| 2304 | + *cookie = cookie; |
|---|
| 2305 | + return kb - kbuf; |
|---|
| 2254 | 2306 | } |
|---|
| 2255 | 2307 | } |
|---|
| 2256 | 2308 | |
|---|
| 2257 | 2309 | n_tty_check_unthrottle(tty); |
|---|
| 2258 | 2310 | |
|---|
| 2259 | | - if (b - buf >= minimum) |
|---|
| 2311 | + if (kb - kbuf >= minimum) |
|---|
| 2260 | 2312 | break; |
|---|
| 2261 | 2313 | if (time) |
|---|
| 2262 | 2314 | timeout = time; |
|---|
| .. | .. |
|---|
| 2268 | 2320 | remove_wait_queue(&tty->read_wait, &wait); |
|---|
| 2269 | 2321 | mutex_unlock(&ldata->atomic_read_lock); |
|---|
| 2270 | 2322 | |
|---|
| 2271 | | - if (b - buf) |
|---|
| 2272 | | - retval = b - buf; |
|---|
| 2323 | + if (kb - kbuf) |
|---|
| 2324 | + retval = kb - kbuf; |
|---|
| 2273 | 2325 | |
|---|
| 2274 | 2326 | return retval; |
|---|
| 2275 | 2327 | } |
|---|
| .. | .. |
|---|
| 2305 | 2357 | ssize_t retval = 0; |
|---|
| 2306 | 2358 | |
|---|
| 2307 | 2359 | /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ |
|---|
| 2308 | | - if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { |
|---|
| 2360 | + if (L_TOSTOP(tty) && file->f_op->write_iter != redirected_tty_write) { |
|---|
| 2309 | 2361 | retval = tty_check_change(tty); |
|---|
| 2310 | 2362 | if (retval) |
|---|
| 2311 | 2363 | return retval; |
|---|