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
--- /dev/null
+From 64a69892afadd6fffaeadc65427bb7601161139d Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 19 Jan 2021 13:46:28 -0800
+Subject: tty: clean up legacy leftovers from n_tty line discipline
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+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 <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
--- /dev/null
+From ddc5fda7456178e2cbc87675b370920d98360daf Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 21 Jan 2021 10:08:15 -0800
+Subject: tty: fix up hung_up_tty_read() conversion
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+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 <jirislaby@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/CAHk-=wh+-rGsa=xruEWdg_fJViFG8rN9bpLrfLz=_yBYh2tBhA@mail.gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
--- /dev/null
+From e71a8d5cf4b4f274740e31b601216071e2a11afa Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 21 Jan 2021 10:17:25 -0800
+Subject: tty: fix up iterate_tty_read() EOVERFLOW handling
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+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 <jirislaby@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/CAHk-=wh+-rGsa=xruEWdg_fJViFG8rN9bpLrfLz=_yBYh2tBhA@mail.gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
--- /dev/null
+From 15ea8ae8e03fdb845ed3ff5d9f11dd5f4f60252c Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 19 Jan 2021 18:14:20 -0800
+Subject: tty: teach n_tty line discipline about the new "cookie continuations"
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+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 <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
--- /dev/null
+From d7fe75cbc23c7d225eee2ef04def239b6603dce7 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+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 <torvalds@linux-foundation.org>
+
+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 <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;