From 3d14ec1fe61aebe3da85a9b8f2c3d61e43d522e6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Sun, 25 Apr 2021 22:02:38 +0100 Subject: [PATCH] iov_iter: Four fixes for ITER_XARRAY Fix four things[1] in the patch that adds ITER_XARRAY[2]: (1) Remove the address_space struct predeclaration. This is a holdover from when it was ITER_MAPPING. (2) Fix _copy_mc_to_iter() so that the xarray segment updates count and iov_offset in the iterator before returning. (3) Fix iov_iter_alignment() to not loop in the xarray case. Because the middle pages are all whole pages, only the end pages need be considered - and this can be reduced to just looking at the start position in the xarray and the iteration size. (4) Fix iov_iter_advance() to limit the size of the advance to no more than the remaining iteration size. Reported-by: Al Viro Signed-off-by: David Howells Reviewed-by: Al Viro Tested-by: Jeff Layton Tested-by: Dave Wysochanski Link: https://lore.kernel.org/r/YIVrJT8GwLI0Wlgx@zeniv-ca.linux.org.uk [1] Link: https://lore.kernel.org/r/161918448151.3145707.11541538916600921083.stgit@warthog.procyon.org.uk [2] --- include/linux/uio.h | 1 - lib/iov_iter.c | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/uio.h b/include/linux/uio.h index 5f5ffc45d4aafe..d3ec87706d7573 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -10,7 +10,6 @@ #include struct page; -struct address_space; struct pipe_inode_info; struct kvec { diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 44fa726a8323cd..61228a6c69f8ba 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -791,6 +791,8 @@ size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i) curr_addr = (unsigned long) from; bytes = curr_addr - s_addr - rem; rcu_read_unlock(); + i->iov_offset += bytes; + i->count -= bytes; return bytes; } }) @@ -1147,6 +1149,7 @@ void iov_iter_advance(struct iov_iter *i, size_t size) return; } if (unlikely(iov_iter_is_xarray(i))) { + size = min(size, i->count); i->iov_offset += size; i->count -= size; return; @@ -1346,6 +1349,8 @@ unsigned long iov_iter_alignment(const struct iov_iter *i) return size | i->iov_offset; return size; } + if (unlikely(iov_iter_is_xarray(i))) + return (i->xarray_start + i->iov_offset) | i->count; iterate_all_kinds(i, size, v, (res |= (unsigned long)v.iov_base | v.iov_len, 0), res |= v.bv_offset | v.bv_len,