* [PATCH v2 1/2] iov_iter: iterate_folioq: fix handling of offset >= folio size
2025-08-11 21:28 [PATCH v2 0/2] iterate_folioq bug when offset==size (Was: [REGRESSION] 9pfs issues on 6.12-rc1) Dominique Martinet via B4 Relay
@ 2025-08-11 21:28 ` Dominique Martinet via B4 Relay
2025-08-11 21:28 ` [PATCH v2 2/2] iov_iter: iov_folioq_get_pages: don't leave empty slot behind Dominique Martinet via B4 Relay
1 sibling, 0 replies; 3+ messages in thread
From: Dominique Martinet via B4 Relay @ 2025-08-11 21:28 UTC (permalink / raw)
To: Matthew Wilcox (Oracle), Christian Brauner, David Howells,
Alexander Viro, Andrew Morton
Cc: Maximilian Bosch, Ryan Lahfa, Christian Theune, Arnout Engelen,
linux-kernel, linux-block, linux-fsdevel, Dominique Martinet,
stable
From: Dominique Martinet <asmadeus@codewreck.org>
It's apparently possible to get an iov advanced all the way up to the
end of the current page we're looking at, e.g.
(gdb) p *iter
$24 = {iter_type = 4 '\004', nofault = false, data_source = false, iov_offset = 4096, {__ubuf_iovec = {
iov_base = 0xffff88800f5bc000, iov_len = 655}, {{__iov = 0xffff88800f5bc000, kvec = 0xffff88800f5bc000,
bvec = 0xffff88800f5bc000, folioq = 0xffff88800f5bc000, xarray = 0xffff88800f5bc000,
ubuf = 0xffff88800f5bc000}, count = 655}}, {nr_segs = 2, folioq_slot = 2 '\002', xarray_start = 2}}
Where iov_offset is 4k with 4k-sized folios
This should have been because we're only in the 2nd slot and there's
another one after this, but iterate_folioq should not try to map a
folio that skips the whole size, and more importantly part here does
not end up zero (because 'PAGE_SIZE - skip % PAGE_SIZE' ends up
PAGE_SIZE and not zero..), so skip forward to the "advance to next
folio" code
Reported-by: Maximilian Bosch <maximilian@mbosch.me>
Reported-by: Ryan Lahfa <ryan@lahfa.xyz>
Reported-by: Christian Theune <ct@flyingcircus.io>
Reported-by: Arnout Engelen <arnout@bzzt.net>
Link: https://lkml.kernel.org/r/D4LHHUNLG79Y.12PI0X6BEHRHW@mbosch.me/
Fixes: db0aa2e9566f ("mm: Define struct folio_queue and ITER_FOLIOQ to handle a sequence of folios")
Cc: stable@vger.kernel.org # v6.12+
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
include/linux/iov_iter.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/iov_iter.h b/include/linux/iov_iter.h
index c4aa58032faf874ee5b29bd37f9e23c479741bef..a77ff9c7e4b21eacd166adb506b79e7ddd723aa1 100644
--- a/include/linux/iov_iter.h
+++ b/include/linux/iov_iter.h
@@ -160,7 +160,7 @@ size_t iterate_folioq(struct iov_iter *iter, size_t len, void *priv, void *priv2
do {
struct folio *folio = folioq_folio(folioq, slot);
- size_t part, remain, consumed;
+ size_t part, remain = 0, consumed;
size_t fsize;
void *base;
@@ -168,6 +168,8 @@ size_t iterate_folioq(struct iov_iter *iter, size_t len, void *priv, void *priv2
break;
fsize = folioq_folio_size(folioq, slot);
+ if (skip >= fsize)
+ goto next;
base = kmap_local_folio(folio, skip);
part = umin(len, PAGE_SIZE - skip % PAGE_SIZE);
remain = step(base, progress, part, priv, priv2);
@@ -177,6 +179,7 @@ size_t iterate_folioq(struct iov_iter *iter, size_t len, void *priv, void *priv2
progress += consumed;
skip += consumed;
if (skip >= fsize) {
+next:
skip = 0;
slot++;
if (slot == folioq_nr_slots(folioq) && folioq->next) {
--
2.50.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] iov_iter: iov_folioq_get_pages: don't leave empty slot behind
2025-08-11 21:28 [PATCH v2 0/2] iterate_folioq bug when offset==size (Was: [REGRESSION] 9pfs issues on 6.12-rc1) Dominique Martinet via B4 Relay
2025-08-11 21:28 ` [PATCH v2 1/2] iov_iter: iterate_folioq: fix handling of offset >= folio size Dominique Martinet via B4 Relay
@ 2025-08-11 21:28 ` Dominique Martinet via B4 Relay
1 sibling, 0 replies; 3+ messages in thread
From: Dominique Martinet via B4 Relay @ 2025-08-11 21:28 UTC (permalink / raw)
To: Matthew Wilcox (Oracle), Christian Brauner, David Howells,
Alexander Viro, Andrew Morton
Cc: Maximilian Bosch, Ryan Lahfa, Christian Theune, Arnout Engelen,
linux-kernel, linux-block, linux-fsdevel, Dominique Martinet
From: Dominique Martinet <asmadeus@codewreck.org>
After advancing into a folioq it makes more sense to point to the next
slot than at the end of the current slot.
This should not be needed for correctness, but this also happens to
"fix" the 9p bug with iterate_folioq() not copying properly.
Acked-by: David Howells <dhowells@redhat.com>
Tested-by: Arnout Engelen <arnout@bzzt.net>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
lib/iov_iter.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index f9193f952f49945297479483755d68a34c6d4ffe..65c05134ab934e1e0bf5d010fff22983bfe9c680 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1032,9 +1032,6 @@ static ssize_t iter_folioq_get_pages(struct iov_iter *iter,
maxpages--;
}
- if (maxpages == 0 || extracted >= maxsize)
- break;
-
if (iov_offset >= fsize) {
iov_offset = 0;
slot++;
@@ -1043,6 +1040,9 @@ static ssize_t iter_folioq_get_pages(struct iov_iter *iter,
slot = 0;
}
}
+
+ if (maxpages == 0 || extracted >= maxsize)
+ break;
}
iter->count = count;
--
2.50.1
^ permalink raw reply related [flat|nested] 3+ messages in thread