[PATCH 4/7] lib/iov_iter: account for iov_offset in iov_iter_single_seg_count() folioq path

From: Josh Law

Date: Fri Mar 13 2026 - 14:13:32 EST


When the block layer calls iov_iter_single_seg_count() to size a
segment for a folioq-backed iterator — as happens during large
buffered writes through cachefiles or fscache — the function returns
the full folio size without subtracting iov_offset. After a partial
transfer has advanced iov_offset into the middle of a folio, this
over-reports the remaining data in the current segment.

The iovec and bvec paths both subtract iov_offset (e.g.
iter_iov(i)->iov_len - i->iov_offset), but the folioq path omits it.

Found by reviewing the function for consistency across iterator types
and comparing each branch's treatment of iov_offset.

Subtract iov_offset from the folio size to match the behavior of the
other iterator types.

Signed-off-by: Josh Law <objecting@xxxxxxxxxxxxx>
---
lib/iov_iter.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 6a7959bfc849..375512beefc5 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -682,7 +682,8 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i)
}
if (unlikely(iov_iter_is_folioq(i)))
return !i->count ? 0 :
- umin(folioq_folio_size(i->folioq, i->folioq_slot), i->count);
+ umin(folioq_folio_size(i->folioq, i->folioq_slot) - i->iov_offset,
+ i->count);
return i->count;
}
EXPORT_SYMBOL(iov_iter_single_seg_count);
--
2.34.1