diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2020-11-12 14:40:37 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2020-11-15 22:12:53 -0500 |
commit | 4bbf439b09c5ac3f8b3e9584fe080375d8d0ad2d (patch) | |
tree | 4c22e0ed68c83609d95949c7a7f2645b0513a8b2 /fs/isofs/util.c | |
parent | d4d50710a8b46082224376ef119a4dbb75b25c56 (diff) | |
download | linux-stable-4bbf439b09c5ac3f8b3e9584fe080375d8d0ad2d.tar.gz linux-stable-4bbf439b09c5ac3f8b3e9584fe080375d8d0ad2d.tar.bz2 linux-stable-4bbf439b09c5ac3f8b3e9584fe080375d8d0ad2d.zip |
fix return values of seq_read_iter()
Unlike ->read(), ->read_iter() instances *must* return the amount
of data they'd left in iterator. For ->read() returning less than
it has actually copied is a QoI issue; read(fd, unmapped_page - 5, 8)
is allowed to fill all 5 bytes of destination and return 4; it's
not nice to caller, but POSIX allows pretty much anything in such
situation, up to and including a SIGSEGV.
generic_file_splice_read() uses pipe-backed iterator as destination;
there a short copy comes from pipe being full, not from running into
an un{mapped,writable} page in the middle of destination as we
have for iovec-backed iterators read(2) uses. And there we rely
upon the ->read_iter() reporting the actual amount it has left
in destination.
Conversion of a ->read() instance into ->read_iter() has to watch
out for that. If you really need an "all or nothing" kind of
behaviour somewhere, you need to do iov_iter_revert() to prune
the partial copy.
In case of seq_read_iter() we can handle short copy just fine;
the data is in m->buf and next call will fetch it from there.
Fixes: d4d50710a8b4 (seq_file: add seq_read_iter)
Tested-by: Nathan Chancellor <natechancellor@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/isofs/util.c')
0 files changed, 0 insertions, 0 deletions