summaryrefslogtreecommitdiff
path: root/include/linux/uio.h
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2022-06-15 02:02:51 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2022-08-08 22:37:18 -0400
commit10f525a8cd7a525e9fc73288bb35428c9cad5e63 (patch)
treeb6f8d6ad9b2c042ec55c437ee23f0088b61d8efe /include/linux/uio.h
parent92acdc4f37207c556baee0ea28ce0823d22b9812 (diff)
ITER_PIPE: cache the type of last buffer
We often need to find whether the last buffer is anon or not, and currently it's rather clumsy: check if ->iov_offset is non-zero (i.e. that pipe is not empty) if so, get the corresponding pipe_buffer and check its ->ops if it's &default_pipe_buf_ops, we have an anon buffer. Let's replace the use of ->iov_offset (which is nowhere near similar to its role for other flavours) with signed field (->last_offset), with the following rules: empty, no buffers occupied: 0 anon, with bytes up to N-1 filled: N zero-copy, with bytes up to N-1 filled: -N That way abs(i->last_offset) is equal to what used to be in i->iov_offset and empty vs. anon vs. zero-copy can be distinguished by the sign of i->last_offset. Checks for "should we extend the last buffer or should we start a new one?" become easier to follow that way. Note that most of the operations can only be done in a sane state - i.e. when the pipe has nothing past the current position of iterator. About the only thing that could be done outside of that state is iov_iter_advance(), which transitions to the sane state by truncating the pipe. There are only two cases where we leave the sane state: 1) iov_iter_get_pages()/iov_iter_get_pages_alloc(). Will be dealt with later, when we make get_pages advancing - the callers are actually happier that way. 2) iov_iter copied, then something is put into the copy. Since they share the underlying pipe, the original gets behind. When we decide that we are done with the copy (original is not usable until then) we advance the original. direct_io used to be done that way; nowadays it operates on the original and we do iov_iter_revert() to discard the excessive data. At the moment there's nothing in the kernel that could do that to ITER_PIPE iterators, so this reason for insane state is theoretical right now. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'include/linux/uio.h')
-rw-r--r--include/linux/uio.h5
1 files changed, 4 insertions, 1 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 85bef84fd294..e7fc29b5ad19 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -40,7 +40,10 @@ struct iov_iter {
bool nofault;
bool data_source;
bool user_backed;
- size_t iov_offset;
+ union {
+ size_t iov_offset;
+ int last_offset;
+ };
size_t count;
union {
const struct iovec *iov;