Skip to content

Commit 709f0f1

Browse files
LiBaokun96tytso
authored andcommitted
ext4: add checks for large folio incompatibilities when BS > PS
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> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Zhang Yi <yi.zhang@huawei.com> Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Message-ID: <20251121090654.631996-24-libaokun@huaweicloud.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1 parent 1a3e9e8 commit 709f0f1

3 files changed

Lines changed: 52 additions & 29 deletions

File tree

fs/ext4/ext4.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1705,7 +1705,9 @@ struct ext4_sb_info {
17051705
unsigned long s_last_trim_minblks;
17061706

17071707
/* minimum folio order of a page cache allocation */
1708-
unsigned int s_min_folio_order;
1708+
u16 s_min_folio_order;
1709+
/* supported maximum folio order, 0 means not supported */
1710+
u16 s_max_folio_order;
17091711

17101712
/* Precomputed FS UUID checksum for seeding other checksums */
17111713
__u32 s_csum_seed;

fs/ext4/inode.c

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5148,41 +5148,23 @@ static int check_igot_inode(struct inode *inode, ext4_iget_flags flags,
51485148
return -EFSCORRUPTED;
51495149
}
51505150

5151-
static bool ext4_should_enable_large_folio(struct inode *inode)
5151+
void ext4_set_inode_mapping_order(struct inode *inode)
51525152
{
51535153
struct super_block *sb = inode->i_sb;
5154+
u16 min_order, max_order;
51545155

5155-
if (!S_ISREG(inode->i_mode))
5156-
return false;
5157-
if (ext4_has_feature_encrypt(sb))
5158-
return false;
5159-
5160-
return true;
5161-
}
5162-
5163-
/*
5164-
* Limit the maximum folio order to 2048 blocks to prevent overestimation
5165-
* of reserve handle credits during the folio writeback in environments
5166-
* where the PAGE_SIZE exceeds 4KB.
5167-
*/
5168-
#define EXT4_MAX_PAGECACHE_ORDER(i) \
5169-
umin(MAX_PAGECACHE_ORDER, (11 + (i)->i_blkbits - PAGE_SHIFT))
5170-
void ext4_set_inode_mapping_order(struct inode *inode)
5171-
{
5172-
u32 max_order;
5156+
max_order = EXT4_SB(sb)->s_max_folio_order;
5157+
if (!max_order)
5158+
return;
51735159

5174-
if (!ext4_should_enable_large_folio(inode))
5160+
min_order = EXT4_SB(sb)->s_min_folio_order;
5161+
if (!min_order && !S_ISREG(inode->i_mode))
51755162
return;
51765163

5177-
if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
5178-
ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
5179-
max_order = EXT4_SB(inode->i_sb)->s_min_folio_order;
5180-
else
5181-
max_order = EXT4_MAX_PAGECACHE_ORDER(inode);
5164+
if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
5165+
max_order = min_order;
51825166

5183-
mapping_set_folio_order_range(inode->i_mapping,
5184-
EXT4_SB(inode->i_sb)->s_min_folio_order,
5185-
max_order);
5167+
mapping_set_folio_order_range(inode->i_mapping, min_order, max_order);
51865168
}
51875169

51885170
struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,

fs/ext4/super.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5042,6 +5042,41 @@ static const char *ext4_has_journal_option(struct super_block *sb)
50425042
return NULL;
50435043
}
50445044

5045+
/*
5046+
* Limit the maximum folio order to 2048 blocks to prevent overestimation
5047+
* of reserve handle credits during the folio writeback in environments
5048+
* where the PAGE_SIZE exceeds 4KB.
5049+
*/
5050+
#define EXT4_MAX_PAGECACHE_ORDER(sb) \
5051+
umin(MAX_PAGECACHE_ORDER, (11 + (sb)->s_blocksize_bits - PAGE_SHIFT))
5052+
static void ext4_set_max_mapping_order(struct super_block *sb)
5053+
{
5054+
struct ext4_sb_info *sbi = EXT4_SB(sb);
5055+
5056+
if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
5057+
sbi->s_max_folio_order = sbi->s_min_folio_order;
5058+
else
5059+
sbi->s_max_folio_order = EXT4_MAX_PAGECACHE_ORDER(sb);
5060+
}
5061+
5062+
static int ext4_check_large_folio(struct super_block *sb)
5063+
{
5064+
const char *err_str = NULL;
5065+
5066+
if (ext4_has_feature_encrypt(sb))
5067+
err_str = "encrypt";
5068+
5069+
if (!err_str) {
5070+
ext4_set_max_mapping_order(sb);
5071+
} else if (sb->s_blocksize > PAGE_SIZE) {
5072+
ext4_msg(sb, KERN_ERR, "bs(%lu) > ps(%lu) unsupported for %s",
5073+
sb->s_blocksize, PAGE_SIZE, err_str);
5074+
return -EINVAL;
5075+
}
5076+
5077+
return 0;
5078+
}
5079+
50455080
static int ext4_load_super(struct super_block *sb, ext4_fsblk_t *lsb,
50465081
int silent)
50475082
{
@@ -5318,6 +5353,10 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
53185353

53195354
ext4_apply_options(fc, sb);
53205355

5356+
err = ext4_check_large_folio(sb);
5357+
if (err < 0)
5358+
goto failed_mount;
5359+
53215360
err = ext4_encoding_init(sb, es);
53225361
if (err)
53235362
goto failed_mount;

0 commit comments

Comments
 (0)