[Concept,16/21] ext4l: Add a CONFIG_EXT4_MBALLOC option

Message ID 20260108185149.1995917-17-sjg@u-boot.org
State New
Headers
Series ext4l: Add Kconfig options to reduce binary size (part P) |

Commit Message

Simon Glass Jan. 8, 2026, 6:51 p.m. UTC
  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(-)
  

Patch

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,