From: Simon Glass <simon.glass@canonical.com> The multiblock allocator (mballoc.c) is required for write operations but adds about 22K to the binary. For read-only builds, this code is unnecessary. Add a CONFIG_EXT4_MBALLOC option that makes mballoc.c conditional. When disabled, inline stubs return appropriate error codes (-EROFS for block allocation, -EOPNOTSUPP for trim) to allow the rest of ext4 to function for read operations. The option is always y when EXT4_WRITE is enabled, and the MBALLOC_PREFETCH option now depends on MBALLOC being enabled. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4/Kconfig | 1 + fs/ext4l/Kconfig | 13 +++++++++++- fs/ext4l/Makefile | 3 ++- fs/ext4l/ext4.h | 54 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index d7798cfb6b9..8ead2244a3c 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -9,6 +9,7 @@ config FS_EXT4 config EXT4_WRITE bool "Enable ext4 filesystem write support" depends on FS_EXT4 || FS_EXT4L + select EXT4_MBALLOC if FS_EXT4L help This provides support for creating and writing new files to an existing ext4 filesystem partition. diff --git a/fs/ext4l/Kconfig b/fs/ext4l/Kconfig index b7520aaab16..fcd5953b6dd 100644 --- a/fs/ext4l/Kconfig +++ b/fs/ext4l/Kconfig @@ -111,9 +111,20 @@ config EXT4_INDIRECT Filesystems without the extents feature will be rejected if this is disabled. Adds about 5K. If unsure, say N. +config EXT4_MBALLOC + bool "Enable ext4 multiblock allocator" + depends on FS_EXT4L + help + Enable the multiblock allocator (mballoc) which is required for + writing to ext4 filesystems. This handles block allocation for + new files and extending existing files. + + For read-only builds, this can be disabled to save about 22K. + If unsure, say Y if you need write support, N for read-only. + config EXT4_MBALLOC_PREFETCH bool "Enable ext4 block bitmap prefetch support" - depends on FS_EXT4L + depends on FS_EXT4L && EXT4_MBALLOC help Enable prefetching of block allocation bitmaps to improve allocation performance. When enabled, the multiblock allocator diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 0f5ee832f2e..8c5ffb8557c 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -8,10 +8,11 @@ obj-y := interface.o support.o stub.o # Core ext4 objects (always needed) obj-y += balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \ extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \ - inode.o mballoc.o mmp.o namei.o \ + inode.o mmp.o namei.o \ page-io.o readpage.o super.o symlink.o fast_commit.o orphan.o # Optional features +obj-$(CONFIG_EXT4_MBALLOC) += mballoc.o obj-$(CONFIG_EXT4_RESIZE) += resize.o obj-$(CONFIG_EXT4_MIGRATE) += migrate.o obj-$(CONFIG_EXT4_MOVE_EXTENT) += move_extent.o diff --git a/fs/ext4l/ext4.h b/fs/ext4l/ext4.h index b8e9f2d8c95..8d4e20e538a 100644 --- a/fs/ext4l/ext4.h +++ b/fs/ext4l/ext4.h @@ -2987,6 +2987,7 @@ int __init ext4_fc_init_dentry_cache(void); void ext4_fc_destroy_dentry_cache(void); /* mballoc.c */ +#ifdef CONFIG_EXT4_MBALLOC extern const struct seq_operations ext4_mb_seq_groups_ops; extern const struct seq_operations ext4_mb_seq_structs_summary_ops; extern int ext4_seq_mb_stats_show(struct seq_file *seq, void *offset); @@ -2997,6 +2998,19 @@ extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *, extern void ext4_discard_preallocations(struct inode *); extern int __init ext4_init_mballoc(void); extern void ext4_exit_mballoc(void); +#else +static inline int ext4_mb_init(struct super_block *sb) { return 0; } +static inline void ext4_mb_release(struct super_block *sb) {} +static inline ext4_fsblk_t ext4_mb_new_blocks(handle_t *h, + struct ext4_allocation_request *ar, int *err) +{ + *err = -EROFS; + return 0; +} +static inline void ext4_discard_preallocations(struct inode *i) {} +static inline int ext4_init_mballoc(void) { return 0; } +static inline void ext4_exit_mballoc(void) {} +#endif extern int __init ext4_init_es(void); extern void ext4_exit_es(void); @@ -3028,29 +3042,57 @@ struct ext4_fs_context { ext4_fsblk_t s_sb_block; }; +#ifdef CONFIG_EXT4_MBALLOC extern ext4_group_t ext4_mb_prefetch(struct super_block *sb, ext4_group_t group, unsigned int nr, int *cnt); extern void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group, unsigned int nr); - -extern void ext4_free_blocks(handle_t *handle, struct inode *inode, - struct buffer_head *bh, ext4_fsblk_t block, - unsigned long count, int flags); extern int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups); extern int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t i, struct ext4_group_desc *desc); +extern void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block, + int len, bool state); +extern void ext4_free_blocks(handle_t *handle, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t block, + unsigned long count, int flags); extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, ext4_fsblk_t block, unsigned long count); extern int ext4_trim_fs(struct super_block *, struct fstrim_range *); extern void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid); -extern void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block, - int len, bool state); static inline bool ext4_mb_cr_expensive(enum criteria cr) { return cr >= CR_GOAL_LEN_SLOW; } +#else +static inline ext4_group_t ext4_mb_prefetch(struct super_block *sb, + ext4_group_t group, unsigned int nr, int *cnt) +{ + *cnt = 0; + return group; +} +static inline void ext4_mb_prefetch_fini(struct super_block *sb, + ext4_group_t group, unsigned int nr) {} +static inline int ext4_mb_alloc_groupinfo(struct super_block *sb, + ext4_group_t ngroups) { return 0; } +static inline int ext4_mb_add_groupinfo(struct super_block *sb, + ext4_group_t i, struct ext4_group_desc *desc) { return 0; } +static inline void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block, + int len, bool state) {} +static inline void ext4_free_blocks(handle_t *handle, struct inode *inode, + struct buffer_head *bh, ext4_fsblk_t block, + unsigned long count, int flags) {} +static inline int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, + ext4_fsblk_t block, unsigned long count) { return -EROFS; } +static inline int ext4_trim_fs(struct super_block *sb, struct fstrim_range *r) +{ + return -EOPNOTSUPP; +} +static inline void ext4_process_freed_data(struct super_block *sb, + tid_t commit_tid) {} +static inline bool ext4_mb_cr_expensive(enum criteria cr) { return false; } +#endif /* inode.c */ void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw, -- 2.43.0