[PATCH 3/6] ceph: use a folio in the READ_INLINE path of ceph_read_iter()

From: Tal Zussman

Date: Tue Aug 25 2026 - 17:50:37 EST


The inline data is read into a scratch buffer that never enters the page
cache, so allocate it with folio_alloc() instead of
__page_cache_alloc(). This drops the cpuset page spreading that
__page_cache_alloc() applies on NUMA systems, which only makes sense for
page cache pages. The temporary buffer here is better off node local.

The mismatched __free_page()/__free_pages() pair both become
folio_put(). The __ceph_do_getattr() locked page plumbing will be
converted in a later patch, so pass &folio->page for now.

Signed-off-by: Tal Zussman <tz2294@xxxxxxxxxxxx>
---
fs/ceph/file.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index f322ba42102d..592e32d1e2d4 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -2264,21 +2264,22 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)

if (retry_op > HAVE_RETRIED && ret >= 0) {
int statret;
- struct page *page = NULL;
+ struct folio *folio = NULL;
loff_t i_size;
int mask = CEPH_STAT_CAP_SIZE;
if (retry_op == READ_INLINE) {
- page = __page_cache_alloc(GFP_KERNEL);
- if (!page)
+ folio = folio_alloc(GFP_KERNEL, 0);
+ if (!folio)
return -ENOMEM;

mask = CEPH_STAT_CAP_INLINE_DATA;
}

- statret = __ceph_do_getattr(inode, page, mask, !!page);
+ statret = __ceph_do_getattr(inode, folio ? &folio->page : NULL,
+ mask, !!folio);
if (statret < 0) {
- if (page)
- __free_page(page);
+ if (folio)
+ folio_put(folio);
if (statret == -ENODATA) {
BUG_ON(retry_op != READ_INLINE);
goto again;
@@ -2295,8 +2296,8 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
iocb->ki_pos + len);
end = min_t(loff_t, end, PAGE_SIZE);
if (statret < end)
- zero_user_segment(page, statret, end);
- ret = copy_page_to_iter(page,
+ folio_zero_segment(folio, statret, end);
+ ret = copy_folio_to_iter(folio,
iocb->ki_pos & ~PAGE_MASK,
end - iocb->ki_pos, to);
iocb->ki_pos += ret;
@@ -2309,7 +2310,7 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
iocb->ki_pos += ret;
read += ret;
}
- __free_pages(page, 0);
+ folio_put(folio);
return read;
}


--
2.39.5