diff mbox series

[RFC,9/9] ext4: enable large folio for regular file

Message ID 20241125114419.903270-10-yi.zhang@huaweicloud.com (mailing list archive)
State New
Headers show
Series ext4: enable large folio for regular files | expand

Commit Message

Zhang Yi Nov. 25, 2024, 11:44 a.m. UTC
From: Zhang Yi <yi.zhang@huawei.com>

Besides fsverity, fscrypt, and data=journal mode, ext4 can support large
folios for regular files. Let's enable this feature.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---

The side effect of this patch is that we will no longer be able to
change the active inode's journal flag through
ext4_change_inode_journal_flag(). Since we always enable large folios
for regular files, but we cannot enable large folios for journal data
mode because it can easily exceed journal handle credits. If we want to
enable journal data mode online for an active inode, we must first drop
all of the inode's page cache and disable large folios before
conversion. However, disabling large folios is currently not permitted
on active inodes because it may not safe, which means we will lose the
ability to convert to online journal mode after this patch.

The data journal mode is not recommended and should probably be removed
in the future, I suppose we don't want to find a way to support this
mode, so can we just kill the online conversion now?

 fs/ext4/ext4.h      |  1 +
 fs/ext4/ext4_jbd2.c |  3 ++-
 fs/ext4/ialloc.c    |  3 +++
 fs/ext4/inode.c     | 19 +++++++++++++++++++
 4 files changed, 25 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 44b0d418143c..48de159a9508 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2983,6 +2983,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
 
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index da4a82456383..8fa0c9bad715 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -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 */
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 7f1a5f90dbbd..cef7aee5ae02 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1333,6 +1333,9 @@  struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
 		}
 	}
 
+	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);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c0179b07d753..8f9a16908503 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4702,6 +4702,22 @@  static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
 	return NULL;
 }
 
+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)
+		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)
@@ -4970,6 +4986,9 @@  struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
 		inode->i_op = &ext4_file_inode_operations;
 		inode->i_fop = &ext4_file_operations;
 		ext4_set_aops(inode);
+
+		if (ext4_should_enable_large_folio(inode))
+			mapping_set_large_folios(inode->i_mapping);
 	} else if (S_ISDIR(inode->i_mode)) {
 		inode->i_op = &ext4_dir_inode_operations;
 		inode->i_fop = &ext4_dir_operations;