From: Greg Kroah-Hartman Date: Fri, 5 Mar 2021 08:53:07 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v4.4.260~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=64ded75694b3569a7566d2fb91a9443f328cfbe0;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: tty-clean-up-legacy-leftovers-from-n_tty-line-discipline.patch tty-fix-up-hung_up_tty_read-conversion.patch tty-fix-up-iterate_tty_read-eoverflow-handling.patch tty-teach-n_tty-line-discipline-about-the-new-cookie-continuations.patch tty-teach-the-n_tty-icanon-case-about-the-new-cookie-continuations-too.patch --- diff --git a/queue-5.10/series b/queue-5.10/series index dcb00b51322..2e164f96f3a 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -91,3 +91,8 @@ remoteproc-mediatek-fix-kernel-test-robot-warning.patch swap-fix-swapfile-read-write-offset.patch powerpc-sstep-check-instruction-validity-against-isa-version-before-emulation.patch powerpc-sstep-fix-incorrect-return-from-analyze_instr.patch +tty-fix-up-iterate_tty_read-eoverflow-handling.patch +tty-fix-up-hung_up_tty_read-conversion.patch +tty-clean-up-legacy-leftovers-from-n_tty-line-discipline.patch +tty-teach-n_tty-line-discipline-about-the-new-cookie-continuations.patch +tty-teach-the-n_tty-icanon-case-about-the-new-cookie-continuations-too.patch diff --git a/queue-5.10/tty-clean-up-legacy-leftovers-from-n_tty-line-discipline.patch b/queue-5.10/tty-clean-up-legacy-leftovers-from-n_tty-line-discipline.patch new file mode 100644 index 00000000000..30211fb3934 --- /dev/null +++ b/queue-5.10/tty-clean-up-legacy-leftovers-from-n_tty-line-discipline.patch @@ -0,0 +1,113 @@ +From 64a69892afadd6fffaeadc65427bb7601161139d Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 19 Jan 2021 13:46:28 -0800 +Subject: tty: clean up legacy leftovers from n_tty line discipline + +From: Linus Torvalds + +commit 64a69892afadd6fffaeadc65427bb7601161139d upstream. + +Back when the line disciplines did their own direct user accesses, they +had to deal with the data copy possibly failing in the middle. + +Now that the user copy is done by the tty_io.c code, that failure case +no longer exists. + +Remove the left-over error handling code that cannot trigger. + +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_tty.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -1955,19 +1955,17 @@ static inline int input_available_p(stru + * read_tail published + */ + +-static int copy_from_read_buf(struct tty_struct *tty, ++static void copy_from_read_buf(struct tty_struct *tty, + unsigned char **kbp, + size_t *nr) + + { + struct n_tty_data *ldata = tty->disc_data; +- int retval; + size_t n; + bool is_eof; + size_t head = smp_load_acquire(&ldata->commit_head); + size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); + +- retval = 0; + n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); + n = min(*nr, n); + if (n) { +@@ -1984,7 +1982,6 @@ static int copy_from_read_buf(struct tty + *kbp += n; + *nr -= n; + } +- return retval; + } + + /** +@@ -2010,9 +2007,9 @@ static int copy_from_read_buf(struct tty + * read_tail published + */ + +-static int canon_copy_from_read_buf(struct tty_struct *tty, +- unsigned char **kbp, +- size_t *nr) ++static void canon_copy_from_read_buf(struct tty_struct *tty, ++ unsigned char **kbp, ++ size_t *nr) + { + struct n_tty_data *ldata = tty->disc_data; + size_t n, size, more, c; +@@ -2022,7 +2019,7 @@ static int canon_copy_from_read_buf(stru + + /* N.B. avoid overrun if nr == 0 */ + if (!*nr) +- return 0; ++ return; + + n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail); + +@@ -2069,7 +2066,6 @@ static int canon_copy_from_read_buf(stru + ldata->push = 0; + tty_audit_push(); + } +- return 0; + } + + /** +@@ -2219,24 +2215,17 @@ static ssize_t n_tty_read(struct tty_str + } + + if (ldata->icanon && !L_EXTPROC(tty)) { +- retval = canon_copy_from_read_buf(tty, &kb, &nr); +- if (retval) +- break; ++ canon_copy_from_read_buf(tty, &kb, &nr); + } else { +- int uncopied; +- + /* Deal with packet mode. */ + if (packet && kb == kbuf) { + *kb++ = TIOCPKT_DATA; + nr--; + } + +- uncopied = copy_from_read_buf(tty, &kb, &nr); +- uncopied += copy_from_read_buf(tty, &kb, &nr); +- if (uncopied) { +- retval = -EFAULT; +- break; +- } ++ /* See comment above copy_from_read_buf() why twice */ ++ copy_from_read_buf(tty, &kb, &nr); ++ copy_from_read_buf(tty, &kb, &nr); + } + + n_tty_check_unthrottle(tty); diff --git a/queue-5.10/tty-fix-up-hung_up_tty_read-conversion.patch b/queue-5.10/tty-fix-up-hung_up_tty_read-conversion.patch new file mode 100644 index 00000000000..4dde0fa9678 --- /dev/null +++ b/queue-5.10/tty-fix-up-hung_up_tty_read-conversion.patch @@ -0,0 +1,58 @@ +From ddc5fda7456178e2cbc87675b370920d98360daf Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Thu, 21 Jan 2021 10:08:15 -0800 +Subject: tty: fix up hung_up_tty_read() conversion + +From: Linus Torvalds + +commit ddc5fda7456178e2cbc87675b370920d98360daf upstream. + +In commit "tty: implement read_iter", I left the read_iter conversion of +the hung up tty case alone, because I incorrectly thought it didn't +matter. + +Jiri showed me the errors of my ways, and pointed out the problems with +that incomplete conversion. Fix it all up. + +Reported-by: Jiri Slaby +Signed-off-by: Linus Torvalds +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/CAHk-=wh+-rGsa=xruEWdg_fJViFG8rN9bpLrfLz=_yBYh2tBhA@mail.gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/tty_io.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -429,8 +429,7 @@ struct tty_driver *tty_find_polling_driv + EXPORT_SYMBOL_GPL(tty_find_polling_driver); + #endif + +-static ssize_t hung_up_tty_read(struct file *file, char __user *buf, +- size_t count, loff_t *ppos) ++static ssize_t hung_up_tty_read(struct kiocb *iocb, struct iov_iter *to) + { + return 0; + } +@@ -502,7 +501,7 @@ static const struct file_operations cons + + static const struct file_operations hung_up_tty_fops = { + .llseek = no_llseek, +- .read = hung_up_tty_read, ++ .read_iter = hung_up_tty_read, + .write_iter = hung_up_tty_write, + .poll = hung_up_tty_poll, + .unlocked_ioctl = hung_up_tty_ioctl, +@@ -929,8 +928,10 @@ static ssize_t tty_read(struct kiocb *io + /* We want to wait for the line discipline to sort out in this + situation */ + ld = tty_ldisc_ref_wait(tty); ++ if (!ld) ++ return hung_up_tty_read(iocb, to); + i = -EIO; +- if (ld && ld->ops->read) ++ if (ld->ops->read) + i = iterate_tty_read(ld, tty, file, to); + tty_ldisc_deref(ld); + diff --git a/queue-5.10/tty-fix-up-iterate_tty_read-eoverflow-handling.patch b/queue-5.10/tty-fix-up-iterate_tty_read-eoverflow-handling.patch new file mode 100644 index 00000000000..68865779439 --- /dev/null +++ b/queue-5.10/tty-fix-up-iterate_tty_read-eoverflow-handling.patch @@ -0,0 +1,64 @@ +From e71a8d5cf4b4f274740e31b601216071e2a11afa Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Thu, 21 Jan 2021 10:17:25 -0800 +Subject: tty: fix up iterate_tty_read() EOVERFLOW handling + +From: Linus Torvalds + +commit e71a8d5cf4b4f274740e31b601216071e2a11afa upstream. + +When I converted the tty_ldisc_ops 'read()' function to take a kernel +pointer, I was a bit too aggressive about the ldisc returning EOVERFLOW. + +Yes, we want to have EOVERFLOW override any partially read data (because +the whole point is that the buffer was too small for the whole packet, +and we don't want to see partial packets), but it shouldn't override a +previous EFAULT. + +And in fact, it really is just EOVERFLOW that is special and should +throw away any partially read data, not "any error". Admittedly +EOVERFLOW is currently the only one that can happen for a continuation +read - and if the first read iteration returns an error we won't have this issue. + +So this is more of a technicality, but let's just make the intent very +explicit, and re-organize the error handling a bit so that this is all +clearer. + +Reported-by: Jiri Slaby +Signed-off-by: Linus Torvalds +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/CAHk-=wh+-rGsa=xruEWdg_fJViFG8rN9bpLrfLz=_yBYh2tBhA@mail.gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/tty_io.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -860,13 +860,20 @@ static int iterate_tty_read(struct tty_l + if (!size) + break; + +- /* +- * A ldisc read error return will override any previously copied +- * data (eg -EOVERFLOW from HDLC) +- */ + if (size < 0) { +- memzero_explicit(kernel_buf, sizeof(kernel_buf)); +- return size; ++ /* Did we have an earlier error (ie -EFAULT)? */ ++ if (retval) ++ break; ++ retval = size; ++ ++ /* ++ * -EOVERFLOW means we didn't have enough space ++ * for a whole packet, and we shouldn't return ++ * a partial result. ++ */ ++ if (retval == -EOVERFLOW) ++ offset = 0; ++ break; + } + + copied = copy_to_iter(kernel_buf, size, to); diff --git a/queue-5.10/tty-teach-n_tty-line-discipline-about-the-new-cookie-continuations.patch b/queue-5.10/tty-teach-n_tty-line-discipline-about-the-new-cookie-continuations.patch new file mode 100644 index 00000000000..4150aa46c90 --- /dev/null +++ b/queue-5.10/tty-teach-n_tty-line-discipline-about-the-new-cookie-continuations.patch @@ -0,0 +1,139 @@ +From 15ea8ae8e03fdb845ed3ff5d9f11dd5f4f60252c Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 19 Jan 2021 18:14:20 -0800 +Subject: tty: teach n_tty line discipline about the new "cookie continuations" + +From: Linus Torvalds + +commit 15ea8ae8e03fdb845ed3ff5d9f11dd5f4f60252c upstream. + +With the conversion to do the tty ldisc read operations in small chunks, +the n_tty line discipline became noticeably slower for throughput +oriented loads, because rather than read things in up to 2kB chunks, it +would return at most 64 bytes per read() system call. + +The cost is mainly all in the "do system calls over and over", not +really in the new "copy to an extra kernel buffer". + +This can be fixed by teaching the n_tty line discipline about the +"cookie continuation" model, which the chunking code supports because +things like hdlc need to be able to handle packets up to 64kB in size. + +Doing that doesn't just get us back to the old performace, but to much +better performance: my stupid "copy 10MB of data over a pty" test +program is now almost twice as fast as it used to be (going down from +0.1s to 0.054s). + +This is entirely because it now creates maximal chunks (which happens to +be "one byte less than one page" due to how we do the circular tty +buffers). + +NOTE! This case only handles the simpler non-icanon case, which is the +one where people may care about throughput. I'm going to do the icanon +case later too, because while performance isn't a major issue for that, +there may be programs that think they'll always get a full line and +don't like the 64-byte chunking for that reason. + +Such programs are arguably buggy (signals etc can cause random partial +results from tty reads anyway), and good programs will handle such +partial reads, but expecting everybody to write "good programs" has +never been a winning policy for the kernel.. + +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_tty.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 42 insertions(+), 10 deletions(-) + +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -1943,19 +1943,17 @@ static inline int input_available_p(stru + * Helper function to speed up n_tty_read. It is only called when + * ICANON is off; it copies characters straight from the tty queue. + * +- * It can be profitably called twice; once to drain the space from +- * the tail pointer to the (physical) end of the buffer, and once +- * to drain the space from the (physical) beginning of the buffer +- * to head pointer. +- * + * Called under the ldata->atomic_read_lock sem + * ++ * Returns true if it successfully copied data, but there is still ++ * more data to be had. ++ * + * n_tty_read()/consumer path: + * caller holds non-exclusive termios_rwsem + * read_tail published + */ + +-static void copy_from_read_buf(struct tty_struct *tty, ++static bool copy_from_read_buf(struct tty_struct *tty, + unsigned char **kbp, + size_t *nr) + +@@ -1978,10 +1976,14 @@ static void copy_from_read_buf(struct tt + /* Turn single EOF into zero-length read */ + if (L_EXTPROC(tty) && ldata->icanon && is_eof && + (head == ldata->read_tail)) +- n = 0; ++ return false; + *kbp += n; + *nr -= n; ++ ++ /* If we have more to copy, let the caller know */ ++ return head != ldata->read_tail; + } ++ return false; + } + + /** +@@ -2129,6 +2131,25 @@ static ssize_t n_tty_read(struct tty_str + int packet; + size_t tail; + ++ /* ++ * Is this a continuation of a read started earler? ++ * ++ * If so, we still hold the atomic_read_lock and the ++ * termios_rwsem, and can just continue to copy data. ++ */ ++ if (*cookie) { ++ if (copy_from_read_buf(tty, &kb, &nr)) ++ return kb - kbuf; ++ ++ /* No more data - release locks and stop retries */ ++ n_tty_kick_worker(tty); ++ n_tty_check_unthrottle(tty); ++ up_read(&tty->termios_rwsem); ++ mutex_unlock(&ldata->atomic_read_lock); ++ *cookie = NULL; ++ return kb - kbuf; ++ } ++ + c = job_control(tty, file); + if (c < 0) + return c; +@@ -2223,9 +2244,20 @@ static ssize_t n_tty_read(struct tty_str + nr--; + } + +- /* See comment above copy_from_read_buf() why twice */ +- copy_from_read_buf(tty, &kb, &nr); +- copy_from_read_buf(tty, &kb, &nr); ++ /* ++ * Copy data, and if there is more to be had ++ * and we have nothing more to wait for, then ++ * let's mark us for retries. ++ * ++ * NOTE! We return here with both the termios_sem ++ * and atomic_read_lock still held, the retries ++ * will release them when done. ++ */ ++ if (copy_from_read_buf(tty, &kb, &nr) && kb - kbuf >= minimum) { ++ remove_wait_queue(&tty->read_wait, &wait); ++ *cookie = cookie; ++ return kb - kbuf; ++ } + } + + n_tty_check_unthrottle(tty); diff --git a/queue-5.10/tty-teach-the-n_tty-icanon-case-about-the-new-cookie-continuations-too.patch b/queue-5.10/tty-teach-the-n_tty-icanon-case-about-the-new-cookie-continuations-too.patch new file mode 100644 index 00000000000..ca00e0a8ef5 --- /dev/null +++ b/queue-5.10/tty-teach-the-n_tty-icanon-case-about-the-new-cookie-continuations-too.patch @@ -0,0 +1,106 @@ +From d7fe75cbc23c7d225eee2ef04def239b6603dce7 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 20 Jan 2021 15:43:38 -0800 +Subject: tty: teach the n_tty ICANON case about the new "cookie continuations" too + +From: Linus Torvalds + +commit d7fe75cbc23c7d225eee2ef04def239b6603dce7 upstream. + +The ICANON case is a bit messy, since it has to look for the line +ending, and has special code to then suppress line ending characters if +they match the __DISABLED_CHAR. So it actually looks up the line ending +even past the point where it knows it won't copy it to the result +buffer. + +That said, apart from all those odd legacy N_TTY ICANON cases, the +actual "should we continue copying" logic isn't really all that +complicated or different from the non-canon case. In fact, the lack of +"wait for at least N characters" arguably makes the repeat case slightly +simpler. It really just boils down to "there's more of the line to be +copied". + +So add the necessarily trivial logic, and now the N_TTY case will give +long result lines even when in canon mode. + +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_tty.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -2009,21 +2009,22 @@ static bool copy_from_read_buf(struct tt + * read_tail published + */ + +-static void canon_copy_from_read_buf(struct tty_struct *tty, ++static bool canon_copy_from_read_buf(struct tty_struct *tty, + unsigned char **kbp, + size_t *nr) + { + struct n_tty_data *ldata = tty->disc_data; + size_t n, size, more, c; + size_t eol; +- size_t tail; ++ size_t tail, canon_head; + int found = 0; + + /* N.B. avoid overrun if nr == 0 */ + if (!*nr) +- return; ++ return false; + +- n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail); ++ canon_head = smp_load_acquire(&ldata->canon_head); ++ n = min(*nr + 1, canon_head - ldata->read_tail); + + tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); + size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); +@@ -2067,7 +2068,11 @@ static void canon_copy_from_read_buf(str + else + ldata->push = 0; + tty_audit_push(); ++ return false; + } ++ ++ /* No EOL found - do a continuation retry if there is more data */ ++ return ldata->read_tail != canon_head; + } + + /** +@@ -2138,8 +2143,13 @@ static ssize_t n_tty_read(struct tty_str + * termios_rwsem, and can just continue to copy data. + */ + if (*cookie) { +- if (copy_from_read_buf(tty, &kb, &nr)) +- return kb - kbuf; ++ if (ldata->icanon && !L_EXTPROC(tty)) { ++ if (canon_copy_from_read_buf(tty, &kb, &nr)) ++ return kb - kbuf; ++ } else { ++ if (copy_from_read_buf(tty, &kb, &nr)) ++ return kb - kbuf; ++ } + + /* No more data - release locks and stop retries */ + n_tty_kick_worker(tty); +@@ -2236,7 +2246,8 @@ static ssize_t n_tty_read(struct tty_str + } + + if (ldata->icanon && !L_EXTPROC(tty)) { +- canon_copy_from_read_buf(tty, &kb, &nr); ++ if (canon_copy_from_read_buf(tty, &kb, &nr)) ++ goto more_to_be_read; + } else { + /* Deal with packet mode. */ + if (packet && kb == kbuf) { +@@ -2254,6 +2265,7 @@ static ssize_t n_tty_read(struct tty_str + * will release them when done. + */ + if (copy_from_read_buf(tty, &kb, &nr) && kb - kbuf >= minimum) { ++more_to_be_read: + remove_wait_queue(&tty->read_wait, &wait); + *cookie = cookie; + return kb - kbuf;