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(-) 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 */ -- 2.43.0