~ubuntu-kernel-test/ubuntu/+source/linux/+git/linus--linux:tty-splice

Last commit made on 2021-01-21
Get this branch:
git clone -b tty-splice https://git.launchpad.net/~ubuntu-kernel-test/ubuntu/+source/linux/+git/linus--linux
Members of Ubuntu Kernel Test can upload to this branch. Log in for directions.

Branch merges

Branch information

Recent commits

2b3da8c... by Linus Torvalds <email address hidden>

tty: fix up iterate_tty_read() EOVERFLOW handling

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 <email address hidden>
Signed-off-by: Linus Torvalds <email address hidden>

1443b92... by Linus Torvalds <email address hidden>

tty: fix up hung_up_tty_read() conversion

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 <email address hidden>
Signed-off-by: Linus Torvalds <email address hidden>

bf6ee85... by Linus Torvalds <email address hidden>

tty: fix up hung_up_tty_write() conversion

In commit "tty: implement write_iter", I left the write_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 <email address hidden>
Signed-off-by: Linus Torvalds <email address hidden>

d7fe75c... by Linus Torvalds <email address hidden>

tty: teach the n_tty ICANON case about the new "cookie continuations" too

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 <email address hidden>

15ea8ae... by Linus Torvalds <email address hidden>

tty: teach n_tty line discipline about the new "cookie continuations"

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 <email address hidden>

64a6989... by Linus Torvalds <email address hidden>

tty: clean up legacy leftovers from n_tty line discipline

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 <email address hidden>

dd78b0c... by Linus Torvalds <email address hidden>

tty: implement read_iter

Now that the ldisc read() function takes kernel pointers, it's fairly
straightforward to make the tty file operations use .read_iter() instead
of .read().

That automatically gives us vread() and friends, and also makes it
possible to do .splice_read() on ttys again.

Fixes: 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops")
Reported-by: Oliver Giles <email address hidden>
Cc: Christoph Hellwig <email address hidden>
Cc: Greg Kroah-Hartman <email address hidden>
Cc: Al Viro <email address hidden>
Signed-off-by: Linus Torvalds <email address hidden>

3b830a9... by Linus Torvalds <email address hidden>

tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer

The tty line discipline .read() function was passed the final user
pointer destination as an argument, which doesn't match the 'write()'
function, and makes it very inconvenient to do a splice method for
ttys.

This is a conversion to use a kernel buffer instead.

NOTE! It does this by passing the tty line discipline ->read() function
an additional "cookie" to fill in, and an offset into the cookie data.

The line discipline can fill in the cookie data with its own private
information, and then the reader will repeat the read until either the
cookie is cleared or it runs out of data.

The only real user of this is N_HDLC, which can use this to handle big
packets, even if the kernel buffer is smaller than the whole packet.

Cc: Christoph Hellwig <email address hidden>
Cc: Greg Kroah-Hartman <email address hidden>
Cc: Al Viro <email address hidden>
Signed-off-by: Linus Torvalds <email address hidden>

9bb48c8... by Linus Torvalds <email address hidden>

tty: implement write_iter

This makes the tty layer use the .write_iter() function instead of the
traditional .write() functionality.

That allows writev(), but more importantly also makes it possible to
enable .splice_write() for ttys, reinstating the "splice to tty"
functionality that was lost in commit 36e2c7421f02 ("fs: don't allow
splice read/write without explicit ops").

Fixes: 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops")
Reported-by: Oliver Giles <email address hidden>
Cc: Christoph Hellwig <email address hidden>
Cc: Greg Kroah-Hartman <email address hidden>
Cc: Al Viro <email address hidden>
Signed-off-by: Linus Torvalds <email address hidden>

2c85ebc... by Linus Torvalds <email address hidden>

Linux 5.10