Re: [f2fs-dev] [PATCH 13/14] f2fs: allow large folio support to writeable files

From: Daeho Jeong

Date: Fri Aug 28 2026 - 13:45:22 EST


On Wed, Aug 26, 2026 at 8:07 AM Nanzhe Zhao via Linux-f2fs-devel
<linux-f2fs-devel@xxxxxxxxxxxxxxxxxxxxx> wrote:
>
> 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);
> +}

In F2FS, newly created files almost always start with inline_data
(`FI_INLINE_DATA`).
Because f2fs_has_inline_data() is true during f2fs_new_inode() / f2fs_iget(),
mapping_set_large_folios is skipped.

When the file later expands and is converted to regular blocks in
f2fs_convert_inline_inode(),
`f2fs_mapping_set_large_folio()` is NEVER called.

As a result, almost NO newly created file will ever use Large Folios
during its lifetime.

Fix: Call `f2fs_mapping_set_large_folio(inode)` inside
`f2fs_convert_inline_inode()` once
inline data is converted. Also consider using the standard
`mapping_set_large_folios(mapping)`
helper instead of `mapping_set_folio_min_order(mapping, 0)`.

Thanks,

> +
> 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
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@xxxxxxxxxxxxxxxxxxxxx
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel