anon_pipe_write() requests PAGE_SIZE bytes when copying into a new pipe page, even when fewer bytes remain in the source iterator. The iterator copy is already clamped to the available data, so no data is copied twice. However, after consuming a non-empty iterator with less than PAGE_SIZE bytes, copy_page_from_iter() enters its loop once more and performs an extra kmap_local_page()/kunmap_local() pair before the zero-byte copy makes it stop. Limit the requested copy size to the remaining iterator count so that the loop exits after copying the available data. This is a performance optimization; the copy semantics are unchanged. UnixBench pipe results on Hygon C86 7490 (Hygon 4): | Threads | Before | After | Improvement | |---------|--------|-------|-------------| | 1 | 835 | 854 | +2.28% | | 256 | 179293 | 182895 | +2.01% | Signed-off-by: Li Qiang --- Thanks, Christian, for the clarification, and Mateusz for taking a look and supporting the change. As Christian pointed out, the iterator copy is already clamped to the available data; this change only avoids an extra kmap round trip. I have updated the subject and commit message accordingly. Changes in v2: - Reword the subject and commit message to describe this as a performance optimization, with no data copied twice. - Explain the extra kmap_local_page()/kunmap_local() pair avoided. - No code changes from v1. fs/pipe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/pipe.c b/fs/pipe.c index 292425a834dd..da5583f7f37d 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -595,7 +595,9 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from) break; } - copied = copy_page_from_iter(page, 0, PAGE_SIZE, from); + copied = copy_page_from_iter(page, 0, + min_t(size_t, PAGE_SIZE, + iov_iter_count(from)), from); if (unlikely(copied < PAGE_SIZE && iov_iter_count(from))) { anon_pipe_put_page(pipe, page); if (!ret) base-commit: 47324d3a5b3abd781295044d01d92d09f184e872 -- 2.43.0