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 --- 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