[PATCH 13/14] f2fs: allow large folio support to writeable files
From: Nanzhe Zhao
Date: Wed Aug 26 2026 - 09:12:38 EST
Now we make all write path support large folios,
so we open permission to let writeable file set
large folio mapping.
Keep fs-layer encrypted files excluded unless inline encryption is
enabled, since f2fs_encrypt_one_page() still encrypts one PAGE_SIZE
page and cannot handle large folios.
Signed-off-by: Nanzhe Zhao <zhaonanzhe@xxxxxxxxxx>
---
fs/f2fs/data.c | 9 ++++++++-
fs/f2fs/f2fs.h | 13 +++++++++++++
fs/f2fs/file.c | 16 ----------------
fs/f2fs/inode.c | 4 +---
fs/f2fs/namei.c | 1 +
5 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 0b167b14a9a5..2e20833c6417 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2955,7 +2955,7 @@ static int f2fs_read_data_large_folio(struct inode *inode,
int ret = 0;
bool folio_in_bio = false;
- if (!IS_IMMUTABLE(inode) || f2fs_compressed_file(inode)) {
+ if (f2fs_compressed_file(inode)) {
if (folio)
folio_unlock(folio);
return -EOPNOTSUPP;
@@ -3321,6 +3321,13 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
if (fscrypt_inode_uses_inline_crypto(inode))
return 0;
+ if (folio_test_large(page_folio(page))) {
+ f2fs_warn_ratelimited(F2FS_I_SB(inode),
+ "large folio does not support fs-layer encryption, ino=%llu",
+ (unsigned long long)inode->i_ino);
+ return -EOPNOTSUPP;
+ }
+
fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page_folio(page),
PAGE_SIZE, 0, GFP_NOFS);
if (IS_ERR(fio->encrypted_page))
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 6ae249bf9aa1..04ed0ea92b26 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -5201,6 +5201,19 @@ static inline bool f2fs_quota_file(struct f2fs_sb_info *sbi, nid_t ino)
return false;
}
+static inline void f2fs_mapping_set_large_folio(struct inode *inode)
+{
+ if (!S_ISREG(inode->i_mode) ||
+ f2fs_has_inline_data(inode) ||
+ f2fs_compressed_file(inode) ||
+ f2fs_quota_file(F2FS_I_SB(inode), inode->i_ino) ||
+ (f2fs_encrypted_file(inode) &&
+ !(inode->i_sb->s_flags & SB_INLINECRYPT)))
+ return;
+
+ mapping_set_folio_min_order(inode->i_mapping, 0);
+}
+
static inline bool f2fs_block_unit_discard(struct f2fs_sb_info *sbi)
{
return F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_BLOCK;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index b82acbc3240f..c8426821e701 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -134,17 +134,6 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
int err = 0;
vm_fault_t ret;
- /*
- * We only support large folio on the read case.
- * Don't make any dirty pages.
- */
- if (unlikely(IS_IMMUTABLE(inode)) ||
- mapping_large_folio_support(inode->i_mapping)) {
- f2fs_err(sbi, "Not expected: immutable: %d large_folio: %d",
- IS_IMMUTABLE(inode),
- mapping_large_folio_support(inode->i_mapping));
- return VM_FAULT_SIGBUS;
- }
if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
err = -EIO;
@@ -698,9 +687,6 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
if (!f2fs_is_compress_backend_ready(inode))
return -EOPNOTSUPP;
- if (mapping_large_folio_support(inode->i_mapping) &&
- filp->f_mode & FMODE_WRITE)
- return -EOPNOTSUPP;
err = fsverity_file_open(inode, filp);
if (err)
@@ -1177,8 +1163,6 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return -EPERM;
if ((attr->ia_valid & ATTR_SIZE)) {
- if (mapping_large_folio_support(inode->i_mapping))
- return -EOPNOTSUPP;
if (IS_DEVICE_ALIASING(inode))
return -EPERM;
if (!f2fs_is_compress_backend_ready(inode))
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 96cc0e777567..7c4b5cdfe276 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -642,9 +642,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &f2fs_file_inode_operations;
inode->i_fop = &f2fs_file_operations;
inode->i_mapping->a_ops = &f2fs_dblock_aops;
- if (IS_IMMUTABLE(inode) && !f2fs_compressed_file(inode) &&
- !f2fs_quota_file(sbi, inode->i_ino))
- mapping_set_folio_min_order(inode->i_mapping, 0);
+ f2fs_mapping_set_large_folio(inode);
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &f2fs_dir_inode_operations;
inode->i_fop = &f2fs_dir_operations;
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index afaab7739283..bdf4e586bfcf 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -341,6 +341,7 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
f2fs_set_inode_flags(inode);
f2fs_init_extent_tree(inode);
+ f2fs_mapping_set_large_folio(inode);
trace_f2fs_new_inode(inode, 0);
return inode;
--
2.43.0