From: Simon Glass <simon.glass@canonical.com> Add inode.c to the Makefile with minimal changes: - Replace Linux kernel includes with ext4_uboot.h - Add cast in ext4_inode_peek_iversion() to fix const qualifier warning - Add __maybe_unused to variables in ext4_print_free_blocks() Update ext4_uboot.h with additional stubs needed by inode.c: - address_space_operations: add migrate_folio, swap_activate members, fix write_begin/write_end/writepages signatures - Add buffer_migrate_folio, buffer_migrate_folio_norefs, noop_dirty_folio Add stub functions in stub.c for inode.c dependencies: - Inline data: ext4_try_to_write_inline_data, ext4_generic_write_inline_data, ext4_write_inline_data_end - xattr: ext4_xattr_delete_inode, ext4_xattr_inode_array_free - JBD2: jbd2_inode_cache, jbd2_journal_try_to_free_buffers, jbd2_journal_init_jbd_inode Also add required stub headers: - linux/mpage.h - multi-page I/O stub - linux/rmap.h - reverse mapping stub - linux/atomic.h - atomic operations stub Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Makefile | 2 +- fs/ext4l/ext4_uboot.h | 523 ++++++++++++++++++++++++++++++++++++++++- fs/ext4l/file.c | 20 +- fs/ext4l/inode.c | 39 +-- fs/ext4l/stub.c | 311 +++++++++++++++++------- include/linux/atomic.h | 0 include/linux/fs.h | 22 +- include/linux/iomap.h | 8 + include/linux/jbd2.h | 3 + include/linux/mpage.h | 14 ++ include/linux/rmap.h | 7 + include/linux/sched.h | 1 + 12 files changed, 804 insertions(+), 146 deletions(-) create mode 100644 include/linux/atomic.h create mode 100644 include/linux/mpage.h create mode 100644 include/linux/rmap.h diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index 4a8a94035b9..f9c0f77b8ed 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -7,6 +7,6 @@ obj-y := interface.o stub.o obj-y += balloc.o bitmap.o block_validity.o ext4_jbd2.o extents.o \ extents_status.o hash.o ialloc.o \ - indirect.o \ + indirect.o inode.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 ea28d0fcc63..3f11fb47544 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -20,6 +20,8 @@ #include <linux/init.h> #include <linux/workqueue.h> #include <linux/cred.h> +#include <linux/fs.h> +#include <linux/iomap.h> /* Rotate left - not available in U-Boot */ static inline u32 rol32(u32 word, unsigned int shift) @@ -165,16 +167,6 @@ typedef unsigned long pgoff_t; #define PAGE_SHIFT 12 #endif -/* File readahead state - stub */ -struct file_ra_state { - pgoff_t start; - unsigned int size; - unsigned int async_size; - unsigned int ra_pages; - unsigned int mmap_miss; - loff_t prev_pos; -}; - /* File mode flags */ #define FMODE_32BITHASH 0x00000001 #define FMODE_64BITHASH 0x00000002 @@ -212,7 +204,7 @@ struct dir_context { }; /* iomap types - only define if linux/iomap.h not included */ -#ifndef _LINUX_IOMAP_H +#ifndef LINUX_IOMAP_H #define IOMAP_MAPPED 0 #define IOMAP_INLINE 1 #define IOMAP_UNWRITTEN 2 @@ -235,7 +227,7 @@ struct iomap_ops { int (*iomap_end)(struct inode *inode, loff_t pos, loff_t length, ssize_t written, unsigned flags, struct iomap *iomap); }; -#endif /* _LINUX_IOMAP_H */ +#endif /* LINUX_IOMAP_H */ /* fiemap types */ #define FIEMAP_FLAG_SYNC 0x00000001 @@ -625,8 +617,125 @@ static inline int bdev_read_only(struct block_device *bdev) /* Inode state bits */ #define I_NEW (1 << 0) #define I_FREEING (1 << 1) +#define I_DIRTY_DATASYNC (1 << 2) + +/* Inode flags for i_flags */ +#define S_SYNC 1 +#define S_NOATIME 2 +#define S_APPEND 4 +#define S_IMMUTABLE 8 +#define S_DAX 16 +#define S_DIRSYNC 32 +#define S_ENCRYPTED 64 +#define S_CASEFOLD 128 +#define S_VERITY 256 + +/* Inode dirty state flags */ +#define I_DIRTY_TIME (1 << 3) + +/* Superblock flags */ +#define SB_LAZYTIME (1 << 25) + +/* iattr valid flags */ +#define ATTR_MODE (1 << 0) +#define ATTR_UID (1 << 1) +#define ATTR_GID (1 << 2) +#define ATTR_SIZE (1 << 3) +#define ATTR_ATIME (1 << 4) +#define ATTR_MTIME (1 << 5) +#define ATTR_CTIME (1 << 6) +#define ATTR_ATIME_SET (1 << 7) +#define ATTR_MTIME_SET (1 << 8) +#define ATTR_FORCE (1 << 9) +#define ATTR_KILL_SUID (1 << 11) +#define ATTR_KILL_SGID (1 << 12) +#define ATTR_TIMES_SET ((1 << 7) | (1 << 8)) + +/* STATX flags and attributes */ +#define STATX_BTIME 0x00000800U +#define STATX_DIOALIGN 0x00002000U +#define STATX_WRITE_ATOMIC 0x00004000U +#define STATX_ATTR_COMPRESSED 0x00000004 +#define STATX_ATTR_IMMUTABLE 0x00000010 +#define STATX_ATTR_APPEND 0x00000020 +#define STATX_ATTR_NODUMP 0x00000040 +#define STATX_ATTR_ENCRYPTED 0x00000800 +#define STATX_ATTR_VERITY 0x00100000 + +/* VM fault return values */ +#define VM_FAULT_SIGBUS 0x0002 +#define VM_FAULT_NOPAGE 0x0010 +#define VM_FAULT_LOCKED 0x0200 + +/* struct path - filesystem path */ +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + +/* struct kstat - stat buffer */ +struct kstat { + u64 ino; + dev_t dev; + umode_t mode; + unsigned int nlink; + uid_t uid; + gid_t gid; + dev_t rdev; + loff_t size; + struct timespec64 atime; + struct timespec64 mtime; + struct timespec64 ctime; + struct timespec64 btime; + u64 blocks; + u32 blksize; + u64 attributes; + u64 attributes_mask; + u32 result_mask; + u32 dio_mem_align; + u32 dio_offset_align; + u32 atomic_write_unit_min; + u32 atomic_write_unit_max; + u32 atomic_write_segments_max; +}; + +/* struct vm_area_struct - virtual memory area */ +struct vm_area_struct { + unsigned long vm_start; + unsigned long vm_end; + struct file *vm_file; + unsigned long vm_flags; +}; -/* inode - minimal stub */ +/* struct page - minimal stub */ +struct page { + unsigned long flags; +}; + +/* struct vm_fault - virtual memory fault info */ +struct vm_fault { + struct vm_area_struct *vma; + unsigned long address; + unsigned int flags; + pgoff_t pgoff; + struct folio *folio; + struct page *page; +}; + +/* Forward declaration for swap */ +struct swap_info_struct; + +/* MAX_PAGECACHE_ORDER - maximum order for page cache allocations */ +#define MAX_PAGECACHE_ORDER 12 + +/* Process flags */ +#define PF_MEMALLOC 0x00000800 + +/* Forward declarations for inode operations */ +struct inode_operations; +struct file_operations; + +/* inode - extended for inode.c */ struct inode { struct super_block *i_sb; unsigned long i_ino; @@ -634,6 +743,7 @@ struct inode { unsigned int i_nlink; loff_t i_size; struct address_space *i_mapping; + struct address_space i_data; kuid_t i_uid; kgid_t i_gid; unsigned long i_blocks; @@ -644,9 +754,18 @@ struct inode { struct timespec64 i_atime; struct timespec64 i_mtime; struct timespec64 i_ctime; + struct list_head i_io_list; + dev_t i_rdev; + const struct inode_operations *i_op; + const struct file_operations *i_fop; }; /* Inode time accessors */ +static inline struct timespec64 inode_get_atime(const struct inode *inode) +{ + return inode->i_atime; +} + static inline struct timespec64 inode_get_mtime(const struct inode *inode) { return inode->i_mtime; @@ -657,6 +776,11 @@ static inline struct timespec64 inode_get_ctime(const struct inode *inode) return inode->i_ctime; } +static inline time_t inode_get_atime_sec(const struct inode *inode) +{ + return inode->i_atime.tv_sec; +} + static inline void simple_inode_init_ts(struct inode *inode) { struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 }; @@ -905,4 +1029,377 @@ static inline ktime_t ktime_sub(ktime_t a, ktime_t b) /* seq_file tokens */ #define SEQ_START_TOKEN ((void *)1) +/* folio - memory page container stub */ +struct folio { + struct address_space *mapping; + unsigned long index; +}; + +/* folio_batch - batch of folios */ +struct folio_batch { + unsigned int nr; + struct folio *folios[16]; +}; + +/* folio operations - stubs */ +#define folio_mark_dirty(f) do { (void)(f); } while (0) +#define offset_in_folio(f, p) ({ (void)(f); (unsigned int)((p) & (PAGE_SIZE - 1)); }) +#define folio_buffers(f) ({ (void)(f); (struct buffer_head *)NULL; }) +#define folio_test_uptodate(f) ({ (void)(f); 1; }) +#define folio_pos(f) ({ (void)(f); 0LL; }) +#define folio_size(f) ({ (void)(f); PAGE_SIZE; }) +#define folio_unlock(f) do { (void)(f); } while (0) +#define folio_put(f) do { (void)(f); } while (0) +#define folio_lock(f) do { (void)(f); } while (0) +#define folio_batch_init(fb) do { (fb)->nr = 0; } while (0) +#define filemap_get_folios(m, i, e, fb) ({ (void)(m); (void)(i); (void)(e); (void)(fb); 0U; }) + +/* xa_mark_t - xarray mark type */ +typedef unsigned int xa_mark_t; + +/* Page cache tags */ +#define PAGECACHE_TAG_DIRTY 0 +#define PAGECACHE_TAG_TOWRITE 1 +#define PAGECACHE_TAG_WRITEBACK 2 + +/* blk_plug - block I/O plugging stub */ +struct blk_plug { + int dummy; +}; +#define blk_start_plug(p) do { (void)(p); } while (0) +#define blk_finish_plug(p) do { (void)(p); } while (0) + +/* Writeback reasons */ +#define WB_REASON_FS_FREE_SPACE 0 + +/* readahead_control stub */ +struct readahead_control { + struct address_space *mapping; + struct file *file; + unsigned long _index; + unsigned int _batch_count; +}; + +#define readahead_pos(rac) ({ (void)(rac); 0LL; }) +#define readahead_length(rac) ({ (void)(rac); 0UL; }) + +/* Forward declarations for address_space_operations */ +struct writeback_control; +struct swap_info_struct; + +/* address_space_operations stub */ +struct address_space_operations { + int (*read_folio)(struct file *, struct folio *); + void (*readahead)(struct readahead_control *); + sector_t (*bmap)(struct address_space *, sector_t); + void (*invalidate_folio)(struct folio *, unsigned long, unsigned long); + bool (*release_folio)(struct folio *, gfp_t); + int (*write_begin)(const struct kiocb *, struct address_space *, loff_t, unsigned, struct folio **, void **); + int (*write_end)(const struct kiocb *, struct address_space *, loff_t, unsigned, unsigned, struct folio *, void *); + int (*writepages)(struct address_space *, struct writeback_control *); + bool (*dirty_folio)(struct address_space *, struct folio *); + bool (*is_partially_uptodate)(struct folio *, size_t, size_t); + int (*error_remove_folio)(struct address_space *, struct folio *); + int (*migrate_folio)(struct address_space *, struct folio *, struct folio *, int); + int (*swap_activate)(struct swap_info_struct *, struct file *, sector_t *); +}; + +/* Stub for buffer_migrate_folio */ +static inline int buffer_migrate_folio(struct address_space *mapping, + struct folio *dst, struct folio *src, int mode) +{ + return -EOPNOTSUPP; +} + +/* Stub for buffer_migrate_folio_norefs */ +static inline int buffer_migrate_folio_norefs(struct address_space *mapping, + struct folio *dst, struct folio *src, int mode) +{ + return -EOPNOTSUPP; +} + +/* Stub for noop_dirty_folio */ +static inline bool noop_dirty_folio(struct address_space *mapping, + struct folio *folio) +{ + return false; +} + +/* Stub implementations for address_space_operations callbacks */ +static inline bool block_is_partially_uptodate(struct folio *folio, + size_t from, size_t count) +{ + return false; +} + +static inline int generic_error_remove_folio(struct address_space *mapping, + struct folio *folio) +{ + return 0; +} + +/* FGP flags for folio_grab_cache */ +#define FGP_ACCESSED 0x00000001 +#define FGP_LOCK 0x00000002 +#define FGP_CREAT 0x00000004 +#define FGP_WRITE 0x00000008 +#define FGP_NOFS 0x00000010 +#define FGP_NOWAIT 0x00000020 +#define FGP_FOR_MMAP 0x00000040 +#define FGP_STABLE 0x00000080 + +/* __filemap_get_folio stub */ +static inline struct folio *__filemap_get_folio(struct address_space *mapping, + pgoff_t index, unsigned int fgp_flags, + gfp_t gfp) +{ + return NULL; +} + +/* projid_t - project ID type */ +typedef unsigned int projid_t; + +/* + * Additional stubs for inode.c + */ + +/* try_cmpxchg - compare and exchange with return value */ +#define try_cmpxchg(ptr, old, new) ({ \ + typeof(*(old)) __old = *(old); \ + typeof(*(ptr)) __ret = cmpxchg(ptr, __old, (new)); \ + if (__ret != __old) \ + *(old) = __ret; \ + __ret == __old; \ +}) + +/* ilog2 - log base 2 */ +#include <log.h> +#define ilog2(n) (fls(n) - 1) + +/* Trace stubs for inode.c */ +#define trace_ext4_begin_ordered_truncate(...) do { } while (0) +#define trace_ext4_evict_inode(...) do { } while (0) +#define trace_ext4_da_update_reserve_space(...) do { } while (0) +#define trace_ext4_da_reserve_space(...) do { } while (0) +#define trace_ext4_da_release_space(...) do { } while (0) +#define trace_ext4_da_write_pages_extent(...) do { } while (0) +#define trace_ext4_writepages(...) do { } while (0) +#define trace_ext4_da_write_folios_start(...) do { } while (0) +#define trace_ext4_da_write_folios_end(...) do { } while (0) +#define trace_ext4_writepages_result(...) do { } while (0) +#define trace_ext4_da_write_begin(...) do { } while (0) +#define trace_ext4_da_write_end(...) do { } while (0) +#define trace_ext4_alloc_da_blocks(...) do { } while (0) +#define trace_ext4_read_folio(...) do { } while (0) +#define trace_ext4_invalidate_folio(...) do { } while (0) +#define trace_ext4_journalled_invalidate_folio(...) do { } while (0) +#define trace_ext4_release_folio(...) do { } while (0) +#define trace_ext4_punch_hole(...) do { } while (0) +#define trace_ext4_truncate_enter(...) do { } while (0) +#define trace_ext4_truncate_exit(...) do { } while (0) +#define trace_ext4_load_inode(...) do { } while (0) +#define trace_ext4_other_inode_update_time(...) do { } while (0) +#define trace_ext4_mark_inode_dirty(...) do { } while (0) +#define trace_ext4_write_begin(...) do { } while (0) +#define trace_ext4_write_end(...) do { } while (0) +#define trace_ext4_journalled_write_end(...) do { } while (0) + +/* DAX stubs - DAX not supported in U-Boot */ +#define IS_DAX(inode) (0) +#define dax_break_layout_final(inode) do { } while (0) +#define dax_writeback_mapping_range(m, bd, wb) ({ (void)(m); (void)(bd); (void)(wb); 0; }) +#define dax_zero_range(i, p, l, d, op) ({ (void)(i); (void)(p); (void)(l); (void)(d); (void)(op); -EOPNOTSUPP; }) +#define dax_break_layout_inode(i, m) ({ (void)(i); (void)(m); 0; }) + +/* Superblock freezing stubs */ +#define sb_start_intwrite(sb) do { (void)(sb); } while (0) +#define sb_end_intwrite(sb) do { (void)(sb); } while (0) +#define sb_start_pagefault(sb) do { (void)(sb); } while (0) +#define sb_end_pagefault(sb) do { (void)(sb); } while (0) + +/* Inode I/O list management */ +#define inode_io_list_del(inode) do { } while (0) +#define inode_is_open_for_write(i) (0) +#define inode_is_dirtytime_only(i) (0) + +/* Folio operations - additional stubs */ +#define folio_zero_segments(f, s1, e1, s2, e2) do { } while (0) +#define folio_zero_new_buffers(f, f2, t) do { } while (0) +#define folio_wait_stable(f) do { } while (0) +#define folio_zero_range(f, s, l) do { } while (0) +#define folio_mark_uptodate(f) do { } while (0) +#define folio_next_index(f) ((f)->index + 1) +#define folio_mapped(f) (0) +#define folio_clear_dirty_for_io(f) ({ (void)(f); 1; }) +#define folio_clear_uptodate(f) do { } while (0) +#define folio_batch_release(fb) do { } while (0) +#define folio_nr_pages(f) (1UL) +#define folio_contains(f, idx) ({ (void)(f); (void)(idx); 1; }) +#define folio_clear_checked(f) do { } while (0) +#define folio_test_dirty(f) (0) +#define folio_test_writeback(f) (0) +#define folio_wait_writeback(f) do { } while (0) +#define folio_clear_dirty(f) do { } while (0) +#define folio_test_checked(f) (0) +#define folio_maybe_dma_pinned(f) (0) +#define folio_set_checked(f) do { } while (0) +#define folio_test_locked(f) (0) +#define folio_mkclean(f) (0) +#define page_folio(page) ((struct folio *)(page)) + +/* Quota stubs - additional */ +#define dquot_claim_block(i, n) ({ (void)(i); (void)(n); 0; }) +#define dquot_reserve_block(i, n) ({ (void)(i); (void)(n); 0; }) +#define dquot_release_reservation_block(i, n) do { } while (0) +#define dquot_initialize_needed(i) (0) +#define dquot_transfer(m, i, a) ({ (void)(m); (void)(i); (void)(a); 0; }) +#define is_quota_modification(m, i, a) ({ (void)(m); (void)(i); (void)(a); 0; }) + +/* Percpu counter sub */ +#define percpu_counter_sub(fbc, amount) ((fbc)->count -= (amount)) + +/* Filemap operations - additional */ +#define filemap_get_folio(m, i) ((struct folio *)NULL) +#define filemap_get_folios_tag(m, s, e, t, fb) ({ (void)(m); (void)(s); (void)(e); (void)(t); (void)(fb); 0U; }) +#define filemap_flush(m) ({ (void)(m); 0; }) +#define filemap_write_and_wait(m) ({ (void)(m); 0; }) +#define filemap_dirty_folio(m, f) ({ (void)(m); (void)(f); false; }) +#define filemap_lock_folio(m, i) ((struct folio *)NULL) +#define filemap_invalidate_lock_shared(m) do { } while (0) +#define filemap_invalidate_unlock_shared(m) do { } while (0) +#define mapping_tagged(m, t) (0) +#define tag_pages_for_writeback(m, s, e) do { } while (0) +#define try_to_writeback_inodes_sb(sb, r) do { } while (0) +#define mapping_gfp_constraint(m, g) (g) +#define mapping_set_folio_order_range(m, l, h) do { } while (0) + +/* Buffer operations - additional */ +#define getblk_unmovable(bd, b, s) ((struct buffer_head *)NULL) +#define create_empty_buffers(f, s, flags) ({ (void)(f); (void)(s); (void)(flags); (struct buffer_head *)NULL; }) +#define bh_offset(bh) (0UL) +#define block_invalidate_folio(f, o, l) do { } while (0) +#define block_write_end(pos, len, copied, folio) ({ (void)(pos); (void)(len); (void)(folio); (copied); }) +#define block_dirty_folio(m, f) ({ (void)(m); (void)(f); false; }) +#define try_to_free_buffers(f) ({ (void)(f); true; }) +#define block_commit_write(f, f2, t) do { } while (0) +#define block_page_mkwrite(v, f, g) ((vm_fault_t)0) +#define map_bh(bh, sb, block) do { } while (0) +#define write_begin_get_folio(iocb, m, idx, l) ({ (void)(iocb); (void)(m); (void)(idx); (void)(l); (struct folio *)NULL; }) + +/* fscrypt stubs - additional */ +#define fscrypt_inode_uses_fs_layer_crypto(i) (0) +#define fscrypt_decrypt_pagecache_blocks(f, l, o) ({ (void)(f); (void)(l); (void)(o); 0; }) +#define fscrypt_zeroout_range(i, lb, pb, l) ({ (void)(i); (void)(lb); (void)(pb); (void)(l); 0; }) +#define fscrypt_limit_io_blocks(i, lb, l) (l) +#define fscrypt_prepare_setattr(d, a) ({ (void)(d); (void)(a); 0; }) +#define fscrypt_dio_supported(i) (1) + +/* fsverity stubs */ +#define fsverity_prepare_setattr(d, a) ({ (void)(d); (void)(a); 0; }) +#define fsverity_active(i) (0) + +/* Inode time setters - needed for ext4.h */ +static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_atime = ts; + return ts; +} + +static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_ctime = ts; + return ts; +} + +/* Inode version operations */ +#define inode_peek_iversion_raw(i) (0ULL) +#define inode_peek_iversion(i) (0ULL) +#define inode_set_flags(i, f, m) do { } while (0) +#define inode_set_iversion_raw(i, v) do { } while (0) +#define inode_set_iversion_queried(i, v) do { } while (0) +#define inode_inc_iversion(i) do { } while (0) + +/* Inode credential helpers */ +static inline unsigned int i_uid_read(const struct inode *inode) +{ + return inode->i_uid.val; +} + +static inline unsigned int i_gid_read(const struct inode *inode) +{ + return inode->i_gid.val; +} + +#define i_uid_needs_update(m, a, i) ({ (void)(m); (void)(a); (void)(i); 0; }) +#define i_gid_needs_update(m, a, i) ({ (void)(m); (void)(a); (void)(i); 0; }) +#define i_uid_update(m, a, i) do { } while (0) +#define i_gid_update(m, a, i) do { } while (0) + +/* Device encoding helpers */ +#ifndef MINORBITS +#define MINORBITS 20 +#endif +#ifndef MINORMASK +#define MINORMASK ((1U << MINORBITS) - 1) +#endif +#ifndef MAJOR +#define MAJOR(dev) ((unsigned int)((dev) >> MINORBITS)) +#endif +#ifndef MINOR +#define MINOR(dev) ((unsigned int)((dev) & MINORMASK)) +#endif +#ifndef MKDEV +#define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi)) +#endif + +#define old_valid_dev(dev) (MAJOR(dev) < 256 && MINOR(dev) < 256) +#define old_encode_dev(dev) ((MAJOR(dev) << 8) | MINOR(dev)) +#define old_decode_dev(dev) MKDEV((dev) >> 8, (dev) & 0xff) +#define new_encode_dev(dev) ((unsigned int)(dev)) +#define new_decode_dev(dev) ((dev_t)(dev)) + +/* UID/GID bit helpers */ +#define low_16_bits(x) ((x) & 0xFFFF) +#define high_16_bits(x) (((x) >> 16) & 0xFFFF) +#define fs_high2lowuid(uid) ((uid) & 0xFFFF) +#define fs_high2lowgid(gid) ((gid) & 0xFFFF) + +/* Inode allocation/state operations */ +#define iget_locked(sb, ino) ((struct inode *)NULL) +#define set_nlink(i, n) do { (i)->i_nlink = (n); } while (0) +#define inode_set_cached_link(i, l, len) do { } while (0) +#define init_special_inode(i, m, d) do { } while (0) +#define make_bad_inode(i) do { } while (0) +#define iget_failed(i) do { } while (0) +#define find_inode_by_ino_rcu(sb, ino) ((struct inode *)NULL) +#define mark_inode_dirty(i) do { } while (0) + +/* Attribute operations */ +#define setattr_prepare(m, d, a) ({ (void)(m); (void)(d); (void)(a); 0; }) +#define setattr_copy(m, i, a) do { } while (0) +#define posix_acl_chmod(m, i, mo) ({ (void)(m); (void)(i); (void)(mo); 0; }) +#define generic_fillattr(m, req, i, s) do { } while (0) +#define generic_fill_statx_atomic_writes(s, u_m, u_M, g) do { } while (0) + +/* Inode flag macros */ +#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) +#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) + +/* File operations */ +#define file_update_time(f) do { } while (0) +#define vmf_fs_error(e) ((vm_fault_t)VM_FAULT_SIGBUS) + +/* iomap stubs */ +#define iomap_bmap(m, b, o) ({ (void)(m); (void)(b); (void)(o); 0UL; }) +#define iomap_swapfile_activate(s, f, sp, o) ({ (void)(s); (void)(f); (void)(sp); (void)(o); -EOPNOTSUPP; }) + +/* Block device alignment */ +#define bdev_dma_alignment(bd) (0) + +/* Truncation */ +#define truncate_inode_pages_final(m) do { } while (0) +#define truncate_pagecache_range(i, s, e) do { } while (0) + #endif /* __EXT4_UBOOT_H__ */ diff --git a/fs/ext4l/file.c b/fs/ext4l/file.c index 7a8b3093218..6cff27e7029 100644 --- a/fs/ext4l/file.c +++ b/fs/ext4l/file.c @@ -20,16 +20,8 @@ */ #include <linux/time.h> -#include <linux/fs.h> -#include <linux/iomap.h> -#include <linux/mount.h> -#include <linux/path.h> -#include <linux/dax.h> -#include <linux/quotaops.h> -#include <linux/pagevec.h> -#include <linux/uio.h> +#include "ext4_uboot.h" #include <linux/mman.h> -#include <linux/backing-dev.h> #include "ext4.h" #include "ext4_jbd2.h" #include "xattr.h" @@ -69,7 +61,7 @@ static bool ext4_should_use_dio(struct kiocb *iocb, struct iov_iter *iter) static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to) { ssize_t ret; - struct inode *inode = file_inode(iocb->ki_filp); + struct inode *inode __maybe_unused = file_inode(iocb->ki_filp); if (iocb->ki_flags & IOCB_NOWAIT) { if (!inode_trylock_shared(inode)) @@ -286,7 +278,7 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb, struct iov_iter *from) { ssize_t ret; - struct inode *inode = file_inode(iocb->ki_filp); + struct inode *inode __maybe_unused = file_inode(iocb->ki_filp); if (iocb->ki_flags & IOCB_NOWAIT) return -EOPNOTSUPP; @@ -402,7 +394,7 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size, return error < 0 ? error : 0; } -static const struct iomap_dio_ops ext4_dio_write_ops = { +static const struct iomap_dio_ops __maybe_unused ext4_dio_write_ops = { .end_io = ext4_dio_write_end_io, }; @@ -809,7 +801,7 @@ static int ext4_file_mmap_prepare(struct vm_area_desc *desc) int ret; struct file *file = desc->file; struct inode *inode = file->f_mapping->host; - struct dax_device *dax_dev = EXT4_SB(inode->i_sb)->s_daxdev; + struct dax_device *dax_dev __maybe_unused = EXT4_SB(inode->i_sb)->s_daxdev; if (file->f_mode & FMODE_WRITE) ret = ext4_emergency_state(inode->i_sb); @@ -935,7 +927,7 @@ static int ext4_file_open(struct inode *inode, struct file *filp) loff_t ext4_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; - loff_t maxbytes = ext4_get_maxbytes(inode); + loff_t maxbytes __maybe_unused = ext4_get_maxbytes(inode); switch (whence) { default: diff --git a/fs/ext4l/inode.c b/fs/ext4l/inode.c index e99306a8f47..dc151c068bb 100644 --- a/fs/ext4l/inode.c +++ b/fs/ext4l/inode.c @@ -19,29 +19,7 @@ * Assorted race fixes, rewrite of ext4_get_block() by Al Viro, 2000 */ -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/time.h> -#include <linux/highuid.h> -#include <linux/pagemap.h> -#include <linux/dax.h> -#include <linux/quotaops.h> -#include <linux/string.h> -#include <linux/buffer_head.h> -#include <linux/writeback.h> -#include <linux/pagevec.h> -#include <linux/mpage.h> -#include <linux/rmap.h> -#include <linux/namei.h> -#include <linux/uio.h> -#include <linux/bio.h> -#include <linux/workqueue.h> -#include <linux/kernel.h> -#include <linux/printk.h> -#include <linux/slab.h> -#include <linux/bitops.h> -#include <linux/iomap.h> -#include <linux/iversion.h> +#include "ext4_uboot.h" #include "ext4_jbd2.h" #include "xattr.h" @@ -1763,9 +1741,9 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd, static void ext4_print_free_blocks(struct inode *inode) { - struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + struct ext4_sb_info *sbi __maybe_unused = EXT4_SB(inode->i_sb); struct super_block *sb = inode->i_sb; - struct ext4_inode_info *ei = EXT4_I(inode); + struct ext4_inode_info *ei __maybe_unused = EXT4_I(inode); ext4_msg(sb, KERN_CRIT, "Total free blocks count %lld", EXT4_C2B(EXT4_SB(inode->i_sb), @@ -2758,7 +2736,7 @@ static int ext4_do_writepages(struct mpage_da_data *mpd) { struct writeback_control *wbc = mpd->wbc; pgoff_t writeback_index = 0; - long nr_to_write = wbc->nr_to_write; + __maybe_unused long nr_to_write = wbc->nr_to_write; int range_whole = 0; int cycled = 1; handle_t *handle = NULL; @@ -3055,7 +3033,7 @@ static int ext4_dax_writepages(struct address_space *mapping, struct writeback_control *wbc) { int ret; - long nr_to_write = wbc->nr_to_write; + __maybe_unused long nr_to_write = wbc->nr_to_write; struct inode *inode = mapping->host; int alloc_ctx; @@ -4541,7 +4519,7 @@ int ext4_inode_attach_jinode(struct inode *inode) */ int ext4_truncate(struct inode *inode) { - struct ext4_inode_info *ei = EXT4_I(inode); + __maybe_unused struct ext4_inode_info *ei = EXT4_I(inode); unsigned int credits; int err = 0, err2; handle_t *handle; @@ -4646,7 +4624,7 @@ out_trace: static inline u64 ext4_inode_peek_iversion(const struct inode *inode) { - if (unlikely(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + if (unlikely(EXT4_I((struct inode *)inode)->i_flags & EXT4_EA_INODE_FL)) return inode_peek_iversion_raw(inode); else return inode_peek_iversion(inode); @@ -6094,7 +6072,8 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path, stat->result_mask |= STATX_DIOALIGN; if (dio_align == 1) { - struct block_device *bdev = inode->i_sb->s_bdev; + __maybe_unused struct block_device *bdev = + inode->i_sb->s_bdev; /* iomap defaults */ stat->dio_mem_align = bdev_dma_alignment(bdev) + 1; diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c index 41550bc48bc..2c9c460f0e7 100644 --- a/fs/ext4l/stub.c +++ b/fs/ext4l/stub.c @@ -9,6 +9,7 @@ * DO NOT use this file as a reference - these are temporary placeholders only. */ +#include "ext4_uboot.h" #include <linux/types.h> struct super_block; @@ -37,18 +38,6 @@ unsigned long ext4_inode_table(struct super_block *sb, void *gdp) return 0; } -struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, - int flags, const char *func, unsigned int line) -{ - return NULL; -} - -int ext4_map_blocks(void *handle, struct inode *inode, - struct ext4_map_blocks *map, int flags) -{ - return 0; -} - void __ext4_error_inode(struct inode *inode, const char *func, unsigned int line, unsigned long block, int error, const char *fmt, ...) @@ -250,194 +239,344 @@ struct extent_status; /* ext4_es_cache_extent is now in extents_status.c */ -int ext4_issue_zeroout(struct inode *inode, unsigned long long lblk, - unsigned long long pblk, unsigned long long len) +/* ext4_es_insert_extent is now in extents_status.c */ + +/* 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) +{ +} + +void ext4_discard_preallocations(struct inode *inode, unsigned int needed) +{ +} + +/* ext4_is_pending is now in extents_status.c */ + +int ext4_convert_inline_data(struct inode *inode) { return 0; } -/* ext4_es_insert_extent is now in extents_status.c */ +void ext4_fc_mark_ineligible(struct super_block *sb, int reason, + void *handle) +{ +} -/* ext4_remove_pending is now in extents_status.c */ +/* ext4_es_lookup_extent is now in extents_status.c */ + +/* ext4_es_remove_extent is now in extents_status.c */ -void ext4_da_release_space(struct inode *inode, int to_free) +/* 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) { } -void ext4_da_update_reserve_space(struct inode *inode, int used, int quota_claim) +void ext4_fc_record_regions(struct super_block *sb, int ino, + unsigned long lblk, unsigned long long pblk, + int len, int mapped) { } -int ext4_get_inode_loc(struct inode *inode, void *iloc) +int ext4_read_bh(struct buffer_head *bh, unsigned int op_flags, + bh_end_io_t *end_io, bool simu_fail) { - return -1; + return 0; } -void ext4_free_blocks(void *handle, struct inode *inode, - struct buffer_head *bh, unsigned long long block, - unsigned long count, int flags) +struct buffer_head *ext4_sb_bread_nofail(struct super_block *sb, + unsigned long long block) { + return NULL; } -int __ext4_mark_inode_dirty(void *handle, struct inode *inode, int flags) +/* + * Stubs for ialloc.c - xattr functions + */ +int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, + struct buffer_head *block_bh, size_t value_len, + bool is_create) { return 0; } -void ext4_discard_preallocations(struct inode *inode, unsigned int needed) +/* ext4_init_security stub is provided by xattr.h */ + +/* + * Stubs for xattr_trusted.c + */ +int ext4_xattr_get(struct inode *inode, int name_index, const char *name, + void *buffer, size_t buffer_size) +{ + return -1; +} + +int ext4_xattr_set(struct inode *inode, int name_index, const char *name, + const void *value, size_t value_len, int flags) +{ + return -1; +} + +/* + * Stubs for orphan.c + */ +struct ext4_iloc; + +void ext4_superblock_csum_set(struct super_block *sb) +{ +} + +int ext4_feature_set_ok(struct super_block *sb, int readonly) +{ + return 1; +} + +/* + * Stubs for inode.c + */ +#include <linux/sched.h> + +/* JBD2 stubs for inode.c */ +int jbd2_journal_blocks_per_folio(struct inode *inode) +{ + return 1; +} + +int jbd2_transaction_committed(void *journal, unsigned int tid) +{ + return 1; +} + + +void __ext4_warning_inode(struct inode *inode, const char *func, + unsigned int line, const char *fmt, ...) { } -int ext4_check_map_extents_env(struct inode *inode) + +/* Readahead */ +int ext4_mpage_readpages(void *mapping, void *rac, void *folio) { return 0; } -int ext4_chunk_trans_extent(struct inode *inode, int nrblocks) +int ext4_readpage_inline(struct inode *inode, void *folio) { return 0; } -int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks) +/* Xattr */ +int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, + void *raw_inode, void *handle) { return 0; } -/* ext4_is_pending is now in extents_status.c */ +void ext4_evict_ea_inode(struct inode *inode) +{ +} -int ext4_meta_trans_blocks(struct inode *inode, int lblk, int pblk) + +/* More JBD2 stubs */ +int jbd2_journal_inode_ranged_write(void *handle, struct inode *inode, + loff_t start, loff_t len) { return 0; } -int ext4_zero_partial_blocks(void *handle, struct inode *inode, - loff_t lstart, loff_t length) + +int ext4_read_bh_lock(struct buffer_head *bh, int op_flags, int nowait) { return 0; } -int ext4_convert_inline_data(struct inode *inode) + +/* Fast commit */ +int ext4_fc_commit(void *journal, unsigned int tid) { return 0; } -int ext4_break_layouts(struct inode *inode) +int ext4_force_commit(struct super_block *sb) { return 0; } -int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) + +/* Inline data */ +int ext4_destroy_inline_data(void *handle, struct inode *inode) { return 0; } -void ext4_fc_mark_ineligible(struct super_block *sb, int reason, - void *handle) +/* I/O submit */ +void ext4_io_submit_init(void *io, void *wbc) { } -void ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, - loff_t len) + +void *ext4_init_io_end(struct inode *inode, int gfp) { + return NULL; } -void ext4_truncate_page_cache_block_range(struct inode *inode, loff_t start, - loff_t len) +void ext4_io_submit(void *io) { } -/* ext4_iomap_report_ops - just a symbol needed for linking */ -char ext4_iomap_report_ops; +void ext4_put_io_end_defer(void *io_end) +{ +} -/* ext4_es_lookup_extent is now in extents_status.c */ +void ext4_put_io_end(void *io_end) +{ +} -/* ext4_es_remove_extent is now in extents_status.c */ +void *ext4_alloc_io_end_vec(void *io_end, unsigned long num) +{ + return NULL; +} -/* 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) +/* JBD2 ordered truncate */ +int jbd2_journal_begin_ordered_truncate(void *ji, loff_t new_size) { + return 0; } -void ext4_fc_record_regions(struct super_block *sb, int ino, - unsigned long lblk, unsigned long long pblk, - int len, int mapped) +void jbd2_journal_invalidate_folio(void *journal, void *folio, + unsigned long off, unsigned int len) { } -int ext4_read_bh(struct buffer_head *bh, unsigned int op_flags, - bh_end_io_t *end_io, bool simu_fail) +int jbd2_log_wait_commit(void *journal, unsigned int tid) { return 0; } -struct buffer_head *ext4_sb_bread_nofail(struct super_block *sb, - unsigned long long block) +/* Fast commit */ +void ext4_fc_track_range(void *handle, struct inode *inode, + unsigned long long start, unsigned long long end) { - return NULL; } -/* - * Stubs for ialloc.c - xattr functions - */ -int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, - struct buffer_head *block_bh, size_t value_len, - bool is_create) + +/* JBD2 journal update locking */ +void jbd2_journal_lock_updates(void *journal) +{ +} + +void jbd2_journal_unlock_updates(void *journal) +{ +} + +int jbd2_journal_flush(void *journal, unsigned int flags) { return 0; } -/* ext4_init_security stub is provided by xattr.h */ -/* - * Stubs for xattr_trusted.c - */ -int ext4_xattr_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) +/* Fast commit */ +void ext4_fc_track_inode(void *handle, struct inode *inode) { - return -1; } -int ext4_xattr_set(struct inode *inode, int name_index, const char *name, - const void *value, size_t value_len, int flags) +void ext4_fc_init_inode(void **head, struct inode *inode) { - return -1; } -/* - * Stubs for orphan.c - */ -struct ext4_iloc; +/* JBD2 */ +int jbd2_journal_inode_ranged_wait(void *handle, struct inode *inode, + loff_t start, loff_t len) +{ + return 0; +} -int ext4_reserve_inode_write(void *handle, struct inode *inode, - struct ext4_iloc *iloc) +/* Inline data */ +int ext4_inline_data_iomap(struct inode *inode, void *iomap) { return 0; } -void ext4_superblock_csum_set(struct super_block *sb) + +/* xattr */ +int __xattr_check_inode(struct inode *inode, void *entry, void *end, + unsigned int size, int check_block) { + return 0; } -int ext4_mark_iloc_dirty(void *handle, struct inode *inode, - struct ext4_iloc *iloc) +int ext4_find_inline_data_nolock(struct inode *inode) { return 0; } -int ext4_truncate(struct inode *inode) + +/* File and inode operations symbols */ +char ext4_file_inode_operations; +char ext4_file_operations; +char ext4_dir_inode_operations; +char ext4_dir_operations; +char ext4_special_inode_operations; +char ext4_symlink_inode_operations; +char ext4_fast_symlink_inode_operations; + + +void ext4_update_dynamic_rev(struct super_block *sb) { +} + + +/* Inline data */ +int ext4_inline_data_truncate(struct inode *inode, int *has_inline) +{ + *has_inline = 0; return 0; } -int ext4_feature_set_ok(struct super_block *sb, int readonly) +int ext4_try_to_write_inline_data(struct address_space *mapping, + struct inode *inode, loff_t pos, + unsigned int len, struct folio **foliop) +{ + return 0; +} + +int ext4_generic_write_inline_data(struct address_space *mapping, + struct inode *inode, loff_t pos, + unsigned int len, struct folio **foliop) +{ + return 0; +} + +int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned int len, + unsigned int copied, struct folio *folio) +{ + return copied; +} + +/* xattr stubs for inode.c */ +int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, + void **array, int extra_credits) +{ + return 0; +} + +void ext4_xattr_inode_array_free(void *array) +{ +} + +/* JBD2 stubs for inode.c */ +struct kmem_cache *jbd2_inode_cache; + +int jbd2_journal_try_to_free_buffers(journal_t *journal, struct folio *folio) { return 1; } -struct buffer_head *ext4_bread(void *handle, struct inode *inode, - unsigned long long block, int create) +void jbd2_journal_init_jbd_inode(void *jinode, struct inode *inode) { - return NULL; } diff --git a/include/linux/atomic.h b/include/linux/atomic.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/include/linux/fs.h b/include/linux/fs.h index 8242d1ca35e..0af81af5644 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -15,6 +15,7 @@ struct inode; struct super_block; struct buffer_head; +struct address_space_operations; /* errseq_t - error sequence type */ typedef u32 errseq_t; @@ -29,16 +30,21 @@ typedef unsigned int fmode_t; /* Buffer operations are in buffer_head.h */ -/* address_space - minimal stub */ +/* address_space - extended for inode.c */ struct address_space { struct inode *host; - errseq_t wb_err; /* For jbd2 error tracking */ + errseq_t wb_err; + unsigned long nrpages; + unsigned long writeback_index; + struct list_head i_private_list; + const struct address_space_operations *a_ops; }; /* block_device - minimal stub */ struct block_device { struct address_space *bd_mapping; void *bd_disk; + struct super_block *bd_super; }; /* errseq functions - stubs */ @@ -52,12 +58,24 @@ static inline int errseq_check_and_advance(errseq_t *eseq, errseq_t *since) return 0; } +/* File readahead state - stub */ +struct file_ra_state { + unsigned long start; + unsigned int size; + unsigned int async_size; + unsigned int ra_pages; + unsigned int mmap_miss; + long long prev_pos; +}; + /* file - minimal stub */ struct file { fmode_t f_mode; struct inode *f_inode; unsigned int f_flags; struct address_space *f_mapping; + void *private_data; + struct file_ra_state f_ra; }; /* Get inode from file */ diff --git a/include/linux/iomap.h b/include/linux/iomap.h index e390dc611ca..3bd4070cfdb 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -5,6 +5,7 @@ #include <linux/types.h> struct bio; +struct dax_device; struct inode; struct iomap_iter; struct kiocb; @@ -37,6 +38,13 @@ struct vm_fault; #define IOMAP_OVERWRITE_ONLY (1 << 6) #define IOMAP_UNSHARE (1 << 7) #define IOMAP_DAX (1 << 8) +#define IOMAP_ATOMIC (1 << 9) + +/* IOMAP_NULL_ADDR indicates a hole/unwritten block address */ +#define IOMAP_NULL_ADDR ((u64)-1) + +/* Additional iomap flags */ +#define IOMAP_F_ATOMIC_BIO (1U << 6) struct iomap { u64 addr; diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index f72d7d4b538..35b68ffc0fd 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -33,6 +33,9 @@ #include <linux/init.h> #endif +/* Transaction ID type */ +typedef unsigned int tid_t; + #define journal_oom_retry 1 /* diff --git a/include/linux/mpage.h b/include/linux/mpage.h new file mode 100644 index 00000000000..571eb342e4f --- /dev/null +++ b/include/linux/mpage.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * include/linux/mpage.h + * + * Contains declarations related to preparing and submitting BIOS which contain + * multiple pagecache pages. + */ + +#ifndef _LINUX_MPAGE_H +#define _LINUX_MPAGE_H + +/* Stub for linux/mpage.h - U-Boot doesn't support multi-page I/O */ + +#endif /* _LINUX_MPAGE_H */ diff --git a/include/linux/rmap.h b/include/linux/rmap.h new file mode 100644 index 00000000000..731d5f7e3c5 --- /dev/null +++ b/include/linux/rmap.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_RMAP_H +#define _LINUX_RMAP_H + +/* Stub for linux/rmap.h - U-Boot doesn't support reverse mapping */ + +#endif /* _LINUX_RMAP_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index fcc7be76e77..c16833f0db1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -15,6 +15,7 @@ struct task_struct { int pid; char comm[16]; void *journal_info; /* For jbd2 */ + unsigned int flags; /* PF_* flags */ }; extern struct task_struct *current; -- 2.43.0