ext4: enable large folio for regular file
authorZhang Yi <yi.zhang@huawei.com>
Mon, 12 May 2025 06:33:19 +0000 (14:33 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 20 May 2025 14:31:12 +0000 (10:31 -0400)
Besides fsverity, fscrypt, and the data=journal mode, ext4 now supports
large folios for regular files. Enable this feature by default. However,
since we cannot change the folio order limitation of mappings on active
inodes, setting the journal=data mode via ioctl on an active inode will
not take immediate effect in non-delalloc mode.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20250512063319.3539411-9-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/ialloc.c
fs/ext4/inode.c

index f329aa0517b4584e20224c1ca39b5f8d908a2396..cda06ed468ca2b28434b730b3eb2401cbce92713 100644 (file)
@@ -2999,6 +2999,7 @@ int ext4_walk_page_buffers(handle_t *handle,
                                     struct buffer_head *bh));
 int do_journal_get_write_access(handle_t *handle, struct inode *inode,
                                struct buffer_head *bh);
+bool ext4_should_enable_large_folio(struct inode *inode);
 #define FALL_BACK_TO_NONDELALLOC 1
 #define CONVERT_INLINE_DATA     2
 
index 135e278c832eec7bfc5539545f5b19c5dd69222f..b3e9b7bd797879ac0bd92ea12005cdd2a37032c2 100644 (file)
@@ -16,7 +16,8 @@ int ext4_inode_journal_mode(struct inode *inode)
            ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
            test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
            (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
-           !test_opt(inode->i_sb, DELALLOC))) {
+           !test_opt(inode->i_sb, DELALLOC) &&
+           !mapping_large_folio_support(inode->i_mapping))) {
                /* We do not support data journalling for encrypted data */
                if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
                        return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
index e7ecc7c8a729696124e883be98690c39d3985f11..4938e78cbadc5aebef713fefd33ff4f5898feee8 100644 (file)
@@ -1336,6 +1336,9 @@ got:
                }
        }
 
+       if (ext4_should_enable_large_folio(inode))
+               mapping_set_large_folios(inode->i_mapping);
+
        ext4_update_inode_fsync_trans(handle, inode, 1);
 
        err = ext4_mark_inode_dirty(handle, inode);
index ed88e5844f46cb758a2fa17d00317aa4d17ddf93..01e42cce572ef3cd0d5d2829f733accd183d7b01 100644 (file)
@@ -4829,6 +4829,23 @@ error:
        return -EFSCORRUPTED;
 }
 
+bool ext4_should_enable_large_folio(struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+
+       if (!S_ISREG(inode->i_mode))
+               return false;
+       if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
+           ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
+               return false;
+       if (ext4_has_feature_verity(sb))
+               return false;
+       if (ext4_has_feature_encrypt(sb))
+               return false;
+
+       return true;
+}
+
 struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
                          ext4_iget_flags flags, const char *function,
                          unsigned int line)
@@ -5147,6 +5164,9 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
                ret = -EFSCORRUPTED;
                goto bad_inode;
        }
+       if (ext4_should_enable_large_folio(inode))
+               mapping_set_large_folios(inode->i_mapping);
+
        ret = check_igot_inode(inode, flags, function, line);
        /*
         * -ESTALE here means there is nothing inherently wrong with the inode,