FAILED: patch "[PATCH] teach copy_page_to_iter() to handle compound pages" failed to apply to 5.4-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 08aa64796016cb47b2ef3d0924653b4d944b0d65 Mon Sep 17 00:00:00 2001
From: Al Viro <[email protected]>
Date: Thu, 29 Apr 2021 20:42:25 -0400
Subject: [PATCH] teach copy_page_to_iter() to handle compound pages
In situation when copy_page_to_iter() got a compound page the current
code would only work on systems with no CONFIG_HIGHMEM. It *is* the majority of real-world setups, or we would've drown in bug reports by now. Still needs fixing.
Current variant works for solitary page; rename that to__copy_page_to_iter() and turn the handling of compound pages into a loop over subpages.
lib/iov_iter.c +25 -3
@@ -957,11 +957,9 @@ static inline bool page_copy_sane(struct page *page, size_t offset, size_t n)return false; } -size_t copy_page_to_iter (struct page *page,size_t offset,size_t bytes, +static size_t __copy_page_to_iter (struct page *page,size_t offset,size_t bytes,struct iov_iter *i) { -if (unlikely (!page_copy_sane (page, offset, bytes))) -return 0 ;if (i->type & (ITER_BVEC |ITER_KVEC |ITER_XARRAY )) {void *kaddr =kmap_atomic (page);size_t wanted =copy_to_iter (kaddr + offset, bytes, i);
@@ -974,6 +972,30 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,else return copy_page_to_iter_pipe (page, offset, bytes, i); } + +size_t copy_page_to_iter (struct page *page,size_t offset,size_t bytes, +struct iov_iter *i) +{ +size_t res =0 ; +if (unlikely (!page_copy_sane (page, offset, bytes))) +return 0 ; + page += offset /PAGE_SIZE ;// first subpage + offset %=PAGE_SIZE ; +while (1 ) { +size_t n =__copy_page_to_iter (page, offset, +min (bytes, (size_t )PAGE_SIZE - offset), i); + res += n; + bytes -= n; +if (!bytes || !n) +break ; + offset += n; +if (offset ==PAGE_SIZE ) { + page++; + offset =0 ; + } + } +return res; +}EXPORT_SYMBOL (copy_page_to_iter); size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,