[PATCH v2 4/5] ceph: convert ceph_fill_inline_data() to take a folio

From: Tal Zussman

Date: Wed Sep 02 2026 - 12:53:15 EST


Convert the internals to folio APIs and pass a folio in from
ceph_fill_inode(). The kmap_atomic()/memcpy() pair becomes
memcpy_to_folio(), which also flushes the dcache, so drop the explicit
flush from the folio creation path. When a locked folio is passed in,
the callers flush after filling it, so the flush in memcpy_to_folio()
is redundant there, but harmless.

This removes the last caller of find_or_create_page() in ceph and saves
six calls to compound_head(). The page_folio() call added in
ceph_fill_inode() goes away once the locked page plumbing is converted.

Remove extern from the function declaration while at it.

Signed-off-by: Tal Zussman <tz2294@xxxxxxxxxxxx>
---
fs/ceph/addr.c | 47 +++++++++++++++++++++--------------------------
fs/ceph/inode.c | 3 ++-
fs/ceph/super.h | 6 +++---
3 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 16681133cf17..71d9f7bdb0c6 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -2190,50 +2190,45 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
}

#ifdef CONFIG_CEPH_FS_INLINE_DATA
-void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
+void ceph_fill_inline_data(struct inode *inode, struct folio *locked_folio,
char *data, size_t len)
{
struct ceph_client *cl = ceph_inode_to_client(inode);
struct address_space *mapping = inode->i_mapping;
- struct page *page;
+ struct folio *folio;

- if (locked_page) {
- page = locked_page;
+ if (locked_folio) {
+ folio = locked_folio;
} else {
if (i_size_read(inode) == 0)
return;
- page = find_or_create_page(mapping, 0,
- mapping_gfp_constraint(mapping,
- ~__GFP_FS));
- if (!page)
+ folio = __filemap_get_folio(mapping, 0,
+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
+ mapping_gfp_constraint(mapping, ~__GFP_FS));
+ if (IS_ERR(folio))
return;
- if (PageUptodate(page)) {
- unlock_page(page);
- put_page(page);
+ if (folio_test_uptodate(folio)) {
+ folio_unlock(folio);
+ folio_put(folio);
return;
}
}

- doutc(cl, "%p %llx.%llx len %zu locked_page %p\n", inode,
- ceph_vinop(inode), len, locked_page);
+ doutc(cl, "%p %llx.%llx len %zu locked_folio %p\n", inode,
+ ceph_vinop(inode), len, locked_folio);

- if (len > 0) {
- void *kaddr = kmap_atomic(page);
- memcpy(kaddr, data, len);
- kunmap_atomic(kaddr);
- }
+ if (len > 0)
+ memcpy_to_folio(folio, 0, data, len);

- if (page != locked_page) {
- if (len < PAGE_SIZE)
- zero_user_segment(page, len, PAGE_SIZE);
- else
- flush_dcache_page(page);
+ if (folio != locked_folio) {
+ if (len < folio_size(folio))
+ folio_zero_segment(folio, len, folio_size(folio));

if (len > 0)
- SetPageUptodate(page);
+ folio_mark_uptodate(folio);

- unlock_page(page);
- put_page(page);
+ folio_unlock(folio);
+ folio_put(folio);
}
}

diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 209e8972287d..21d72b7667bc 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1454,7 +1454,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
ceph_fscache_register_inode_cookie(inode);

if (fill_inline)
- ceph_fill_inline_data(inode, locked_page,
+ ceph_fill_inline_data(inode,
+ locked_page ? page_folio(locked_page) : NULL,
iinfo->inline_data, iinfo->inline_len);

if (wake)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index f3d99027e193..ed750ea73d85 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1434,8 +1434,8 @@ int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invali

#ifdef CONFIG_CEPH_FS_INLINE_DATA
extern int ceph_uninline_data(struct file *file);
-extern void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
- char *data, size_t len);
+void ceph_fill_inline_data(struct inode *inode, struct folio *locked_folio,
+ char *data, size_t len);

static inline u64 ceph_inline_version(const struct ceph_inode_info *ci)
{
@@ -1459,7 +1459,7 @@ static inline int ceph_uninline_data(struct file *file)
}

static inline void ceph_fill_inline_data(struct inode *inode,
- struct page *locked_page,
+ struct folio *locked_folio,
char *data, size_t len)
{
}

--
2.39.5