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

Josh Law posted 7 patches 3 weeks, 3 days ago
[PATCH 4/7] lib/iov_iter: account for iov_offset in iov_iter_single_seg_count() folioq path
Posted by Josh Law 3 weeks, 3 days ago
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@objecting.org>
---
 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