[PATCH v2 14/14] f2fs: make compressed files compatible with large folio

From: Nanzhe Zhao

Date: Tue Sep 15 2026 - 00:25:48 EST


The compression flag is the hint indicates that the inode can be
compressed, when the inode is using large folio, we expected it keeps
using the large folio read/write paths and its data stays uncompressed
on disk until the inode is evicted and re-read

Let f2fs_write_begin() skip the compression overwrite preparation for
such inodes and remove the compressed-file gate in
f2fs_read_data_large_folio() so the data is simply read/written as
regular blocks.

For the same reason, reject F2FS_IOC_COMPRESS_FILE with -EOPNOTSUPP
once the inode mapping is switched to large folios.

Signed-off-by: Nanzhe Zhao <zhaonanzhe@xxxxxxxxxx>
---
Documentation/filesystems/f2fs.rst | 10 ++++++++++
fs/f2fs/compress.c | 2 ++
fs/f2fs/data.c | 9 ++-------
fs/f2fs/file.c | 7 +++++++
4 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 771216f45207..b4f436ffd9ac 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -941,6 +941,16 @@ Compression implementation
reserved via ioctl(F2FS_IOC_RESERVE_COMPRESS_BLOCKS) or the file size is
truncated to zero.

+- Compression and large folios are not effective at the same time on a file:
+ a compressed inode does not use large folios, while an inode which is
+ using large folios keeps its data uncompressed on disk. If the compression
+ flag is set on an inode that is already using large folios, the flag works
+ as a hint until the inode is evicted: the inode keeps using the large folio
+ read/write paths, f2fs_write_begin() skips the compression overwrite
+ preparation, and ioctl(F2FS_IOC_COMPRESS_FILE) fails with -EOPNOTSUPP.
+ Once the inode is evicted and read back, it uses order-0 folios again and
+ compression is applied as usual.
+
Compress metadata layout::

[Dnode Structure]
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index b130e43b4566..fa0f8449a12c 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -78,6 +78,8 @@ bool f2fs_is_compressed_page(struct folio *folio)
return false;
if (folio_test_f2fs_nonpointer(folio))
return false;
+ if (f2fs_folio_has_ffs(folio))
+ return false;

f2fs_bug_on(F2FS_F_SB(folio),
*((u32 *)folio->private) != F2FS_COMPRESSED_PAGE_MAGIC);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c9dba8d0ad3d..f5421334ecf3 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2941,12 +2941,6 @@ static int f2fs_read_data_large_folio(struct inode *inode,
int ret = 0;
bool folio_in_bio = false;

- if (f2fs_compressed_file(inode)) {
- if (folio)
- folio_unlock(folio);
- return -EOPNOTSUPP;
- }
-
map.m_seg_type = NO_CHECK_TYPE;

if (rac)
@@ -4828,7 +4822,8 @@ static int f2fs_write_begin(const struct kiocb *iocb,
}

#ifdef CONFIG_F2FS_FS_COMPRESSION
- if (f2fs_compressed_file(inode)) {
+ if (f2fs_compressed_file(inode) &&
+ !mapping_large_folio_support(inode->i_mapping)) {
int ret;
struct page *page;

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index db71cadefabd..c5cb0b0384b6 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -5002,6 +5002,13 @@ static int f2fs_ioc_compress_file(struct file *filp)
if (!(filp->f_mode & FMODE_WRITE))
return -EBADF;

+ /*
+ * The mapping is already using large folios, where the data is kept
+ * uncompressed, so refuse to start compressing the file.
+ */
+ if (mapping_large_folio_support(inode->i_mapping))
+ return -EOPNOTSUPP;
+
f2fs_balance_fs(sbi, true);

ret = mnt_want_write_file(filp);
--
2.43.0