[Concept,07/10] ext4l: Add mballoc.c to build

Message ID 20251221113820.812060-8-sjg@u-boot.org
State New
Headers
Series ext4l: Add more ext4 files to the build (part E) |

Commit Message

Simon Glass Dec. 21, 2025, 11:38 a.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Add the multiblock allocator (mballoc.c) to the build. This implements
the ext4 block allocation routines.

Stubs added for:
- Per-CPU operations (simplified to single-threaded)
- XArray operations
- RCU list operations
- Block device properties
- Various trace functions
- Atomic operations (atomic_sub, atomic64_sub, atomic_inc_return)
- WARN_RATELIMIT, folio_get, array_index_nospec
- seq_operations for procfs
- DEFINE_RAW_FLEX macro

Remove stub functions that are now properly implemented:
- ext4_mb_new_blocks
- ext4_free_blocks
- ext4_discard_preallocations
- ext4_mb_mark_bb

Add ext4_fc_replay_check_excluded stub for fast commit replay.
Add file member to struct seq_file for procfs compatibility.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 fs/ext4l/Makefile         |   3 +-
 fs/ext4l/ext4_uboot.h     | 203 +++++++++++++++++++++++++++++++++++++-
 fs/ext4l/mballoc.c        |  10 +-
 fs/ext4l/stub.c           |  31 ++----
 include/linux/seq_file.h  |   1 +
 include/linux/slab.h      |   2 +-
 include/linux/workqueue.h |   4 +
 7 files changed, 222 insertions(+), 32 deletions(-)
  

Patch

diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile
index 80797722fe2..dc3858165c3 100644
--- a/fs/ext4l/Makefile
+++ b/fs/ext4l/Makefile
@@ -7,6 +7,7 @@  obj-y := interface.o stub.o
 
 obj-y	+= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
 		extents_status.o file.o fsync.o hash.o ialloc.o \
-		indirect.o inline.o inode.o namei.o super.o symlink.o xattr.o \
+		indirect.o inline.o inode.o mballoc.o \
+		namei.o super.o symlink.o xattr.o \
 		xattr_hurd.o xattr_trusted.o \
 		xattr_user.o orphan.o
diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h
index fc8a2f98bdb..9ea3afdd798 100644
--- a/fs/ext4l/ext4_uboot.h
+++ b/fs/ext4l/ext4_uboot.h
@@ -1193,8 +1193,13 @@  static inline ktime_t ktime_sub(ktime_t a, ktime_t b)
 
 /* folio - memory page container stub */
 struct folio {
-	struct address_space *mapping;
+	struct page *page;
 	unsigned long index;
+	struct address_space *mapping;
+	unsigned long flags;
+	void *data;
+	struct buffer_head *private;
+	int _refcount;
 };
 
 /* folio_batch - batch of folios */
@@ -2364,4 +2369,200 @@  void dquot_free_block(struct inode *inode, loff_t nr);
 #define dquot_resume(sb, type)		do { (void)(sb); (void)(type); } while (0)
 #define sb_any_quota_suspended(sb)	({ (void)(sb); 0; })
 
+/*
+ * Stubs for mballoc.c
+ */
+
+/* XArray stub structure */
+struct xarray {
+	int dummy;
+};
+
+/* Per-CPU stubs - U-Boot is single-threaded */
+#define DEFINE_PER_CPU(type, name)	type name
+#define per_cpu(var, cpu)		(var)
+#define per_cpu_ptr(ptr, cpu)		(ptr)
+#define this_cpu_inc(var)		((var)++)
+#define this_cpu_read(var)		(var)
+#define for_each_possible_cpu(cpu)	for ((cpu) = 0; (cpu) < 1; (cpu)++)
+#define smp_processor_id()		0
+
+/* XArray function stubs */
+#define xa_init(xa)			do { } while (0)
+#define xa_destroy(xa)			do { } while (0)
+#define xa_load(xa, index)		((void *)NULL)
+#define xa_erase(xa, index)		do { (void)(xa); (void)(index); } while (0)
+#define xa_insert(xa, index, entry, gfp) ({ (void)(xa); (void)(index); (void)(entry); (void)(gfp); 0; })
+#define xa_empty(xa)			({ (void)(xa); 1; })
+
+/* XArray iteration stubs - iterate zero times */
+#define xa_for_each(xa, index, entry) \
+	for ((index) = 0, (entry) = NULL; 0; )
+
+#define xa_for_each_range(xa, index, entry, start, end) \
+	for ((index) = (start), (entry) = NULL; 0; )
+
+/* Bit operations for little-endian bitmaps */
+#define __clear_bit_le(bit, addr)	clear_bit_le(bit, addr)
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+	unsigned char *p = (unsigned char *)addr + (nr >> 3);
+
+	*p &= ~(1 << (nr & 7));
+}
+
+#define find_next_bit_le(addr, size, offset) \
+	ext4_find_next_bit_le(addr, size, offset)
+
+static inline unsigned long ext4_find_next_bit_le(const void *addr,
+						  unsigned long size,
+						  unsigned long offset)
+{
+	const unsigned char *p = addr;
+	unsigned long bit;
+
+	for (bit = offset; bit < size; bit++) {
+		if (p[bit >> 3] & (1 << (bit & 7)))
+			return bit;
+	}
+	return size;
+}
+
+/* Atomic64 operations */
+#define atomic64_inc(v)			do { (void)(v); } while (0)
+#define atomic64_add(i, v)		do { (void)(i); (void)(v); } while (0)
+
+/* CPU cycle counter stub */
+#define get_cycles()			(0ULL)
+
+/* folio_address - get virtual address of folio data */
+#undef folio_address
+#define folio_address(folio)		((folio)->data)
+
+/* Trace stubs for mballoc.c */
+#define trace_ext4_mb_bitmap_load(sb, group) \
+	do { (void)(sb); (void)(group); } while (0)
+#define trace_ext4_mb_buddy_bitmap_load(sb, group) \
+	do { (void)(sb); (void)(group); } while (0)
+#define trace_ext4_mballoc_alloc(ac) \
+	do { (void)(ac); } while (0)
+#define trace_ext4_mballoc_prealloc(ac) \
+	do { (void)(ac); } while (0)
+#define trace_ext4_mballoc_discard(sb, inode, group, start, len) \
+	do { (void)(sb); (void)(inode); (void)(group); (void)(start); (void)(len); } while (0)
+#define trace_ext4_mballoc_free(sb, inode, group, start, len) \
+	do { (void)(sb); (void)(inode); (void)(group); (void)(start); (void)(len); } while (0)
+#define trace_ext4_mb_release_inode_pa(pa, block, count) \
+	do { (void)(pa); (void)(block); (void)(count); } while (0)
+#define trace_ext4_mb_release_group_pa(sb, pa) \
+	do { (void)(sb); (void)(pa); } while (0)
+#define trace_ext4_mb_new_inode_pa(ac, pa) \
+	do { (void)(ac); (void)(pa); } while (0)
+#define trace_ext4_mb_new_group_pa(ac, pa) \
+	do { (void)(ac); (void)(pa); } while (0)
+
+/* sb_end_intwrite stub */
+#define sb_end_intwrite(sb)		do { (void)(sb); } while (0)
+
+/* WARN_RATELIMIT - just evaluate condition, no warning in U-Boot */
+#define WARN_RATELIMIT(condition, ...) (condition)
+
+/* folio_get - increment folio refcount (no-op in U-Boot) */
+#define folio_get(f)			do { (void)(f); } while (0)
+
+/* array_index_nospec - bounds checking without speculation (no-op in U-Boot) */
+#define array_index_nospec(index, size) (index)
+
+/* atomic_inc_return - increment and return new value */
+static inline int atomic_inc_return(atomic_t *v)
+{
+	return ++(v->counter);
+}
+
+/* pde_data - proc dir entry data (not supported in U-Boot) */
+#define pde_data(inode)			((void *)NULL)
+
+/* seq_operations for procfs iteration */
+struct seq_operations {
+	void *(*start)(struct seq_file *m, loff_t *pos);
+	void (*stop)(struct seq_file *m, void *v);
+	void *(*next)(struct seq_file *m, void *v, loff_t *pos);
+	int (*show)(struct seq_file *m, void *v);
+};
+
+/* DEFINE_RAW_FLEX - define a flexible array struct on the stack (stubbed to NULL) */
+#define DEFINE_RAW_FLEX(type, name, member, count) \
+	type *name = NULL
+
+/* Block layer constants */
+#define BLK_MAX_SEGMENT_SIZE		65536
+
+/* order_base_2 - log2 rounded up */
+#define order_base_2(n)			ilog2(roundup_pow_of_two(n))
+
+/* num_possible_cpus - number of possible CPUs (always 1 in U-Boot) */
+#define num_possible_cpus()		1
+
+/* Per-CPU allocation stubs */
+#define alloc_percpu(type)		((type *)kzalloc(sizeof(type), GFP_KERNEL))
+#define free_percpu(ptr)		kfree(ptr)
+
+/* Block device properties */
+#define bdev_nonrot(bdev)		({ (void)(bdev); 0; })
+
+/* Trace stub for discard */
+#define trace_ext4_discard_blocks(sb, blk, count) \
+	do { (void)(sb); (void)(blk); (void)(count); } while (0)
+
+/* sb_issue_discard - issue discard request (no-op in U-Boot) */
+#define sb_issue_discard(sb, sector, nr_sects, gfp, flags) \
+	({ (void)(sb); (void)(sector); (void)(nr_sects); (void)(gfp); (void)(flags); 0; })
+
+/* Atomic operations */
+#define atomic_sub(i, v)		((v)->counter -= (i))
+#define atomic64_sub(i, v)		((v)->counter -= (i))
+#define atomic_dec_and_test(v)		(--((v)->counter) == 0)
+
+/* RCU list operations - use regular list operations in U-Boot */
+#define list_for_each_entry_rcu(pos, head, member, ...) \
+	list_for_each_entry(pos, head, member)
+#define list_del_rcu(entry)		list_del(entry)
+#define list_add_rcu(new, head)		list_add(new, head)
+#define list_add_tail_rcu(new, head)	list_add_tail(new, head)
+#define rcu_read_lock()			do { } while (0)
+#define rcu_read_unlock()		do { } while (0)
+#define synchronize_rcu()		do { } while (0)
+#define rcu_assign_pointer(p, v)	((p) = (v))
+#define rcu_dereference(p)		(p)
+
+/* raw_cpu_ptr - get pointer to per-CPU data for current CPU */
+#define raw_cpu_ptr(ptr)		(ptr)
+
+/* Scheduler stubs */
+#define schedule_timeout_uninterruptible(t) do { } while (0)
+#define need_resched()			(0)
+
+/* Trace stubs for mballoc.c */
+#define trace_ext4_discard_preallocations(inode, cnt) \
+	do { (void)(inode); (void)(cnt); } while (0)
+#define trace_ext4_mb_discard_preallocations(sb, needed) \
+	do { (void)(sb); (void)(needed); } while (0)
+#define trace_ext4_request_blocks(ar) \
+	do { (void)(ar); } while (0)
+#define trace_ext4_allocate_blocks(ar, block) \
+	do { (void)(ar); (void)(block); } while (0)
+#define trace_ext4_free_blocks(inode, block, count, flags) \
+	do { (void)(inode); (void)(block); (void)(count); (void)(flags); } while (0)
+#define trace_ext4_trim_extent(sb, group, start, count) \
+	do { (void)(sb); (void)(group); (void)(start); (void)(count); } while (0)
+#define trace_ext4_trim_all_free(sb, group, start, max) \
+	do { (void)(sb); (void)(group); (void)(start); (void)(max); } while (0)
+
+/* Block device operations */
+#define sb_find_get_block_nonatomic(sb, block) \
+	({ (void)(sb); (void)(block); (struct buffer_head *)NULL; })
+#define bdev_discard_granularity(bdev) \
+	({ (void)(bdev); 0U; })
+
 #endif /* __EXT4_UBOOT_H__ */
diff --git a/fs/ext4l/mballoc.c b/fs/ext4l/mballoc.c
index 9087183602e..b58d72dfd26 100644
--- a/fs/ext4l/mballoc.c
+++ b/fs/ext4l/mballoc.c
@@ -9,16 +9,10 @@ 
  * mballoc.c contains the multiblocks allocation routines
  */
 
+#include "ext4_uboot.h"
+
 #include "ext4_jbd2.h"
 #include "mballoc.h"
-#include <linux/log2.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/nospec.h>
-#include <linux/backing-dev.h>
-#include <linux/freezer.h>
-#include <trace/events/ext4.h>
-#include <kunit/static_stub.h>
 
 /*
  * MUSTDO:
diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c
index e5cb69be5b1..ca8a2bc0f91 100644
--- a/fs/ext4l/stub.c
+++ b/fs/ext4l/stub.c
@@ -118,11 +118,7 @@  int jbd2_trans_will_send_data_barrier(journal_t *journal, unsigned long tid)
 /* ext4_mark_group_bitmap_corrupted is now in super.c */
 /* __ext4_warning is now in super.c */
 
-unsigned long long ext4_mb_new_blocks(void *handle, void *ar, int *errp)
-{
-	*errp = -1;
-	return 0;
-}
+/* ext4_mb_new_blocks is now in mballoc.c */
 
 /* ext4_free_group_clusters is now in super.c */
 /* ext4_clear_inode is now in super.c */
@@ -172,15 +168,9 @@  struct extent_status;
 
 /* ext4_remove_pending is now in extents_status.c */
 
-void ext4_free_blocks(void *handle, struct inode *inode,
-		      struct buffer_head *bh, unsigned long long block,
-		      unsigned long count, int flags)
-{
-}
+/* ext4_free_blocks is now in mballoc.c */
 
-void ext4_discard_preallocations(struct inode *inode, unsigned int needed)
-{
-}
+/* ext4_discard_preallocations is now in mballoc.c */
 
 /* ext4_is_pending is now in extents_status.c */
 /* ext4_convert_inline_data is now in inline.c */
@@ -196,10 +186,7 @@  void ext4_fc_mark_ineligible(struct super_block *sb, int reason,
 
 /* ext4_es_find_extent_range is now in extents_status.c */
 
-void ext4_mb_mark_bb(struct super_block *sb, unsigned long long block,
-		     int len, int state)
-{
-}
+/* ext4_mb_mark_bb is now in mballoc.c */
 
 void ext4_fc_record_regions(struct super_block *sb, int ino,
 			    unsigned long lblk, unsigned long long pblk,
@@ -207,6 +194,11 @@  void ext4_fc_record_regions(struct super_block *sb, int ino,
 {
 }
 
+int ext4_fc_replay_check_excluded(struct super_block *sb, unsigned long long blk)
+{
+	return 0;
+}
+
 /* ext4_read_bh is now in super.c */
 /* ext4_sb_bread_nofail is now in super.c */
 
@@ -773,10 +765,7 @@  void atomic_add(int val, atomic_t *v)
 	v->counter += val;
 }
 
-void atomic64_add(s64 val, atomic64_t *v)
-{
-	v->counter += val;
-}
+/* atomic64_add is now a macro in ext4_uboot.h */
 
 /* Discard */
 unsigned int bdev_max_discard_sectors(struct block_device *bdev)
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index fb5dbf97708..5b6495d1003 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -9,6 +9,7 @@ 
 
 struct seq_file {
 	void *private;
+	struct file *file;
 };
 
 #define seq_printf(m, fmt, ...)		do { } while (0)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index e83817cc7ff..2b374641534 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -90,7 +90,7 @@  struct kmem_cache {
 };
 
 struct kmem_cache *get_mem(int element_sz);
-#define kmem_cache_create(a, sz, c, d, e)	({ (void)(e); get_mem(sz); })
+#define kmem_cache_create(a, sz, c, d, e)	({ (void)(a); (void)(e); get_mem(sz); })
 void *kmem_cache_alloc(struct kmem_cache *obj, gfp_t flag);
 
 static inline void *kmem_cache_zalloc(struct kmem_cache *obj, gfp_t flags)
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 1952f62623c..66f61fa6e77 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -79,4 +79,8 @@  static inline void destroy_workqueue(struct workqueue_struct *wq)
 {
 }
 
+/* System workqueues - all stubs in U-Boot */
+#define system_dfl_wq		((struct workqueue_struct *)1)
+#define system_wq		((struct workqueue_struct *)1)
+
 #endif /* _LINUX_WORKQUEUE_H */