| Message ID | 20251107144249.435029-24-libaokun@huaweicloud.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series | ext4: enable block size larger than page size | expand |
On Fri 07-11-25 22:42:48, libaokun@huaweicloud.com wrote: > From: Baokun Li <libaokun1@huawei.com> > > Supporting a block size greater than the page size (BS > PS) requires > support for large folios. However, several features (e.g., encrypt) > do not yet support large folios. > > To prevent conflicts, this patch adds checks at mount time to prohibit > these features from being used when BS > PS. Since these features cannot > be changed on remount, there is no need to check on remount. > > This patch adds s_max_folio_order, initialized during mount according to > filesystem features and mount options. If s_max_folio_order is 0, large > folios are disabled. > > With this in place, ext4_set_inode_mapping_order() can be simplified by > checking s_max_folio_order, avoiding redundant checks. > > Signed-off-by: Baokun Li <libaokun1@huawei.com> Looks good. Feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > fs/ext4/ext4.h | 4 +++- > fs/ext4/inode.c | 39 ++++++++++----------------------------- > fs/ext4/super.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 54 insertions(+), 30 deletions(-) > > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > index 4bc0b2b7288a..79dc231d6e22 100644 > --- a/fs/ext4/ext4.h > +++ b/fs/ext4/ext4.h > @@ -1696,7 +1696,9 @@ struct ext4_sb_info { > unsigned long s_last_trim_minblks; > > /* minimum folio order of a page cache allocation */ > - unsigned int s_min_folio_order; > + u16 s_min_folio_order; > + /* supported maximum folio order, 0 means not supported */ > + u16 s_max_folio_order; > > /* Precomputed FS UUID checksum for seeding other checksums */ > __u32 s_csum_seed; > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c > index b95826e4a419..d53dc5b794d4 100644 > --- a/fs/ext4/inode.c > +++ b/fs/ext4/inode.c > @@ -5146,42 +5146,23 @@ static int check_igot_inode(struct inode *inode, ext4_iget_flags flags, > return -EFSCORRUPTED; > } > > -static bool ext4_should_enable_large_folio(struct inode *inode) > +void ext4_set_inode_mapping_order(struct inode *inode) > { > struct super_block *sb = inode->i_sb; > + u16 min_order, max_order; > > - if (!S_ISREG(inode->i_mode)) > - return false; > - if (ext4_has_feature_encrypt(sb)) > - return false; > - > - return true; > -} > - > -/* > - * Limit the maximum folio order to 2048 blocks to prevent overestimation > - * of reserve handle credits during the folio writeback in environments > - * where the PAGE_SIZE exceeds 4KB. > - */ > -#define EXT4_MAX_PAGECACHE_ORDER(i) \ > - umin(MAX_PAGECACHE_ORDER, (11 + (i)->i_blkbits - PAGE_SHIFT)) > -void ext4_set_inode_mapping_order(struct inode *inode) > -{ > - u32 max_order; > + max_order = EXT4_SB(sb)->s_max_folio_order; > + if (!max_order) > + return; > > - if (!ext4_should_enable_large_folio(inode)) > + min_order = EXT4_SB(sb)->s_min_folio_order; > + if (!min_order && !S_ISREG(inode->i_mode)) > return; > > - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || > - ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) || > - ext4_has_feature_verity(inode->i_sb)) > - max_order = EXT4_SB(inode->i_sb)->s_min_folio_order; > - else > - max_order = EXT4_MAX_PAGECACHE_ORDER(inode); > + if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) > + max_order = min_order; > > - mapping_set_folio_order_range(inode->i_mapping, > - EXT4_SB(inode->i_sb)->s_min_folio_order, > - max_order); > + mapping_set_folio_order_range(inode->i_mapping, min_order, max_order); > } > > struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, > diff --git a/fs/ext4/super.c b/fs/ext4/super.c > index 0d32370a459a..6735152dd219 100644 > --- a/fs/ext4/super.c > +++ b/fs/ext4/super.c > @@ -5040,6 +5040,43 @@ static const char *ext4_has_journal_option(struct super_block *sb) > return NULL; > } > > +/* > + * Limit the maximum folio order to 2048 blocks to prevent overestimation > + * of reserve handle credits during the folio writeback in environments > + * where the PAGE_SIZE exceeds 4KB. > + */ > +#define EXT4_MAX_PAGECACHE_ORDER(sb) \ > + umin(MAX_PAGECACHE_ORDER, (11 + (sb)->s_blocksize_bits - PAGE_SHIFT)) > +static void ext4_set_max_mapping_order(struct super_block *sb) > +{ > + struct ext4_sb_info *sbi = EXT4_SB(sb); > + > + if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) > + sbi->s_max_folio_order = sbi->s_min_folio_order; > + else if (ext4_has_feature_verity(sb)) > + sbi->s_max_folio_order = sbi->s_min_folio_order; > + else > + sbi->s_max_folio_order = EXT4_MAX_PAGECACHE_ORDER(sb); > +} > + > +static int ext4_check_large_folio(struct super_block *sb) > +{ > + const char *err_str = NULL; > + > + if (ext4_has_feature_encrypt(sb)) > + err_str = "encrypt"; > + > + if (!err_str) { > + ext4_set_max_mapping_order(sb); > + } else if (sb->s_blocksize > PAGE_SIZE) { > + ext4_msg(sb, KERN_ERR, "bs(%lu) > ps(%lu) unsupported for %s", > + sb->s_blocksize, PAGE_SIZE, err_str); > + return -EINVAL; > + } > + > + return 0; > +} > + > static int ext4_load_super(struct super_block *sb, ext4_fsblk_t *lsb, > int silent) > { > @@ -5316,6 +5353,10 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) > > ext4_apply_options(fc, sb); > > + err = ext4_check_large_folio(sb); > + if (err < 0) > + goto failed_mount; > + > err = ext4_encoding_init(sb, es); > if (err) > goto failed_mount; > -- > 2.46.1 >
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 4bc0b2b7288a..79dc231d6e22 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1696,7 +1696,9 @@ struct ext4_sb_info { unsigned long s_last_trim_minblks; /* minimum folio order of a page cache allocation */ - unsigned int s_min_folio_order; + u16 s_min_folio_order; + /* supported maximum folio order, 0 means not supported */ + u16 s_max_folio_order; /* Precomputed FS UUID checksum for seeding other checksums */ __u32 s_csum_seed; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b95826e4a419..d53dc5b794d4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5146,42 +5146,23 @@ static int check_igot_inode(struct inode *inode, ext4_iget_flags flags, return -EFSCORRUPTED; } -static bool ext4_should_enable_large_folio(struct inode *inode) +void ext4_set_inode_mapping_order(struct inode *inode) { struct super_block *sb = inode->i_sb; + u16 min_order, max_order; - if (!S_ISREG(inode->i_mode)) - return false; - if (ext4_has_feature_encrypt(sb)) - return false; - - return true; -} - -/* - * Limit the maximum folio order to 2048 blocks to prevent overestimation - * of reserve handle credits during the folio writeback in environments - * where the PAGE_SIZE exceeds 4KB. - */ -#define EXT4_MAX_PAGECACHE_ORDER(i) \ - umin(MAX_PAGECACHE_ORDER, (11 + (i)->i_blkbits - PAGE_SHIFT)) -void ext4_set_inode_mapping_order(struct inode *inode) -{ - u32 max_order; + max_order = EXT4_SB(sb)->s_max_folio_order; + if (!max_order) + return; - if (!ext4_should_enable_large_folio(inode)) + min_order = EXT4_SB(sb)->s_min_folio_order; + if (!min_order && !S_ISREG(inode->i_mode)) return; - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || - ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) || - ext4_has_feature_verity(inode->i_sb)) - max_order = EXT4_SB(inode->i_sb)->s_min_folio_order; - else - max_order = EXT4_MAX_PAGECACHE_ORDER(inode); + if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) + max_order = min_order; - mapping_set_folio_order_range(inode->i_mapping, - EXT4_SB(inode->i_sb)->s_min_folio_order, - max_order); + mapping_set_folio_order_range(inode->i_mapping, min_order, max_order); } struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0d32370a459a..6735152dd219 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5040,6 +5040,43 @@ static const char *ext4_has_journal_option(struct super_block *sb) return NULL; } +/* + * Limit the maximum folio order to 2048 blocks to prevent overestimation + * of reserve handle credits during the folio writeback in environments + * where the PAGE_SIZE exceeds 4KB. + */ +#define EXT4_MAX_PAGECACHE_ORDER(sb) \ + umin(MAX_PAGECACHE_ORDER, (11 + (sb)->s_blocksize_bits - PAGE_SHIFT)) +static void ext4_set_max_mapping_order(struct super_block *sb) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + + if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) + sbi->s_max_folio_order = sbi->s_min_folio_order; + else if (ext4_has_feature_verity(sb)) + sbi->s_max_folio_order = sbi->s_min_folio_order; + else + sbi->s_max_folio_order = EXT4_MAX_PAGECACHE_ORDER(sb); +} + +static int ext4_check_large_folio(struct super_block *sb) +{ + const char *err_str = NULL; + + if (ext4_has_feature_encrypt(sb)) + err_str = "encrypt"; + + if (!err_str) { + ext4_set_max_mapping_order(sb); + } else if (sb->s_blocksize > PAGE_SIZE) { + ext4_msg(sb, KERN_ERR, "bs(%lu) > ps(%lu) unsupported for %s", + sb->s_blocksize, PAGE_SIZE, err_str); + return -EINVAL; + } + + return 0; +} + static int ext4_load_super(struct super_block *sb, ext4_fsblk_t *lsb, int silent) { @@ -5316,6 +5353,10 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ext4_apply_options(fc, sb); + err = ext4_check_large_folio(sb); + if (err < 0) + goto failed_mount; + err = ext4_encoding_init(sb, es); if (err) goto failed_mount;