From: Simon Glass <simon.glass@canonical.com> Add file.c which provides file operations for ext4l filesystem. Changes needed for file.c support: - Add i_writecount and i_rwsem fields to struct inode - Add IOMAP_DIO_* flags to linux/iomap.h - Add vm_operations_struct definition - Add VM flags (VM_SHARED, VM_HUGEPAGE, etc.) - Add vm_area_desc and pipe_inode_info structures - Add FMODE_* flags and SEEK_HOLE/SEEK_DATA to linux/fs.h - Add vfsmount, path structs and f_path to struct file - Add inode_trylock*, lockdep_assert_held_write macros - Add filemap_fault, filemap_map_pages stubs - Add inode_operations struct definition - Add various stubs: d_path, fscrypt_file_open, fsverity_file_open, dquot_file_open, sb_start_intwrite_trylock, ext4_listxattr Simplify ext4_file_operations and ext4_file_inode_operations initializers to use only the members defined in U-Boot's structs. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- fs/ext4l/Makefile | 2 +- fs/ext4l/ext4_uboot.h | 105 ++++++++++++++++++++++++++++++++++++++++-- fs/ext4l/file.c | 20 +------- fs/ext4l/stub.c | 14 +++--- include/linux/fs.h | 21 +++++++++ include/linux/iomap.h | 8 ++++ 6 files changed, 140 insertions(+), 30 deletions(-) diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile index c4fe972d426..73083e82cd8 100644 --- a/fs/ext4l/Makefile +++ b/fs/ext4l/Makefile @@ -6,7 +6,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 hash.o ialloc.o \ + extents_status.o file.o hash.o ialloc.o \ indirect.o inode.o \ super.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 4f0cb4cf13d..5f466dbf005 100644 --- a/fs/ext4l/ext4_uboot.h +++ b/fs/ext4l/ext4_uboot.h @@ -237,6 +237,10 @@ struct iomap_ops { int (*iomap_end)(struct inode *inode, loff_t pos, loff_t length, ssize_t written, unsigned flags, struct iomap *iomap); }; + +/* iomap DIO flags */ +#define IOMAP_DIO_UNWRITTEN (1 << 0) +#define IOMAP_DIO_FORCE_WAIT (1 << 1) #endif /* LINUX_IOMAP_H */ /* fiemap types */ @@ -549,6 +553,22 @@ struct dentry { /* vm_fault_t - stub */ typedef unsigned int vm_fault_t; +/* VM flags */ +#define VM_SHARED 0x00000008 +#define VM_WRITE 0x00000002 +#define VM_HUGEPAGE 0x01000000 +#define FAULT_FLAG_WRITE 0x01 + +/* pipe_inode_info - forward declaration */ +struct pipe_inode_info; + +/* vm_area_desc - for mmap_prepare */ +struct vm_area_desc { + struct file *file; + unsigned long vm_flags; + const struct vm_operations_struct *vm_ops; +}; + /* Forward declarations for function prototypes */ struct kstat; struct path; @@ -698,11 +718,7 @@ static inline int bdev_read_only(struct block_device *bdev) #define VM_FAULT_NOPAGE 0x0010 #define VM_FAULT_LOCKED 0x0200 -/* struct path - filesystem path */ -struct path { - struct vfsmount *mnt; - struct dentry *dentry; -}; +/* struct path is defined in linux/fs.h */ /* struct kstat - stat buffer */ struct kstat { @@ -753,6 +769,15 @@ struct vm_fault { struct page *page; }; +/* vm_operations_struct - virtual memory area operations */ +struct vm_operations_struct { + vm_fault_t (*fault)(struct vm_fault *vmf); + vm_fault_t (*huge_fault)(struct vm_fault *vmf, unsigned int order); + vm_fault_t (*page_mkwrite)(struct vm_fault *vmf); + vm_fault_t (*pfn_mkwrite)(struct vm_fault *vmf); + vm_fault_t (*map_pages)(struct vm_fault *vmf, pgoff_t start, pgoff_t end); +}; + /* Forward declaration for swap */ struct swap_info_struct; @@ -789,6 +814,8 @@ struct inode { dev_t i_rdev; const struct inode_operations *i_op; const struct file_operations *i_fop; + atomic_t i_writecount; /* Count of writers */ + struct rw_semaphore i_rwsem; /* inode lock */ }; /* Inode time accessors */ @@ -941,17 +968,45 @@ static inline unsigned long memweight(const void *ptr, size_t bytes) #define inode_unlock(inode) do { } while (0) #define inode_lock_shared(inode) do { } while (0) #define inode_unlock_shared(inode) do { } while (0) +#define inode_trylock(inode) (1) +#define inode_trylock_shared(inode) (1) #define inode_dio_wait(inode) do { } while (0) +/* Lock debugging - no-ops in U-Boot */ +#define lockdep_assert_held_write(l) do { } while (0) +#define lockdep_assert_held(l) do { } while (0) + /* File operations */ #define file_modified(file) ({ (void)(file); 0; }) +#define file_accessed(file) do { (void)(file); } while (0) + +/* Security checks - no security in U-Boot */ +#define IS_NOSEC(inode) (1) /* Filemap operations */ #define filemap_invalidate_lock(m) do { } while (0) #define filemap_invalidate_unlock(m) do { } while (0) +#define filemap_invalidate_lock_shared(m) do { } while (0) +#define filemap_invalidate_unlock_shared(m) do { } while (0) #define filemap_write_and_wait_range(m, s, e) ({ (void)(m); (void)(s); (void)(e); 0; }) #define truncate_pagecache(i, s) do { } while (0) #define pagecache_isize_extended(i, f, t) do { } while (0) +#define invalidate_mapping_pages(m, s, e) do { (void)(m); (void)(s); (void)(e); } while (0) + +/* Filemap fault handlers - stubs */ +static inline vm_fault_t filemap_fault(struct vm_fault *vmf) +{ + return 0; +} + +static inline vm_fault_t filemap_map_pages(struct vm_fault *vmf, + pgoff_t start, pgoff_t end) +{ + return 0; +} + +/* DAX device mapping check - always false in U-Boot */ +#define daxdev_mapping_supported(f, i, d) ({ (void)(f); (void)(i); (void)(d); 1; }) /* Inode time/size operations */ #define inode_newsize_ok(i, s) ({ (void)(i); (void)(s); 0; }) @@ -1245,9 +1300,25 @@ typedef unsigned int projid_t; /* 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_intwrite_trylock(sb) ({ (void)(sb); 1; }) #define sb_start_pagefault(sb) do { (void)(sb); } while (0) #define sb_end_pagefault(sb) do { (void)(sb); } while (0) +/* d_path - get pathname - stub returns empty path */ +static inline char *d_path(const struct path *path, char *buf, int buflen) +{ + if (buflen > 0) + buf[0] = '\0'; + return buf; +} + +/* fscrypt/fsverity stubs */ +#define fscrypt_file_open(i, f) ({ (void)(i); (void)(f); 0; }) +#define fsverity_file_open(i, f) ({ (void)(i); (void)(f); 0; }) + +/* Quota file open - stub */ +#define dquot_file_open(i, f) ({ (void)(i); (void)(f); 0; }) + /* Inode I/O list management */ #define inode_io_list_del(inode) do { } while (0) #define inode_is_open_for_write(i) (0) @@ -1428,6 +1499,15 @@ static inline unsigned int i_gid_read(const struct inode *inode) #define file_update_time(f) do { } while (0) #define vmf_fs_error(e) ((vm_fault_t)VM_FAULT_SIGBUS) +/* VFS file operations for file.c */ +#define generic_file_read_iter(iocb, to) ({ (void)(iocb); (void)(to); 0; }) +#define filemap_splice_read(f, p, pipe, l, fl) ({ (void)(f); (void)(p); (void)(pipe); (void)(l); (void)(fl); 0; }) +#define generic_write_checks(iocb, from) ({ (void)(iocb); (void)(from); 0; }) +#define generic_perform_write(iocb, from) ({ (void)(iocb); (void)(from); 0; }) +#define generic_write_sync(iocb, count) ({ (void)(iocb); (count); }) +#define generic_atomic_write_valid(iocb, from) ({ (void)(iocb); (void)(from); true; }) +#define vfs_setpos(file, offset, maxsize) ({ (void)(file); (void)(maxsize); (offset); }) + /* 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; }) @@ -1485,6 +1565,21 @@ struct file_operations { int (*release)(struct inode *, struct file *); }; +/* inode_operations - for file and directory operations */ +struct inode_operations { + int (*getattr)(struct mnt_idmap *, const struct path *, + struct kstat *, u32, unsigned int); + ssize_t (*listxattr)(struct dentry *, char *, size_t); + int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64, u64); + int (*setattr)(struct mnt_idmap *, struct dentry *, struct iattr *); + struct posix_acl *(*get_inode_acl)(struct inode *, int, bool); + int (*set_acl)(struct mnt_idmap *, struct dentry *, + struct posix_acl *, int); + int (*fileattr_get)(struct dentry *, struct file_kattr *); + int (*fileattr_set)(struct mnt_idmap *, struct dentry *, + struct file_kattr *); +}; + /* file open helper */ #define simple_open(i, f) ({ (void)(i); (void)(f); 0; }) diff --git a/fs/ext4l/file.c b/fs/ext4l/file.c index 6cff27e7029..b4127dbe913 100644 --- a/fs/ext4l/file.c +++ b/fs/ext4l/file.c @@ -952,36 +952,20 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int whence) return vfs_setpos(file, offset, maxbytes); } +/* U-Boot simplified file operations */ const struct file_operations ext4_file_operations = { .llseek = ext4_llseek, - .read_iter = ext4_file_read_iter, - .write_iter = ext4_file_write_iter, - .iopoll = iocb_bio_iopoll, .unlocked_ioctl = ext4_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ext4_compat_ioctl, -#endif - .mmap_prepare = ext4_file_mmap_prepare, .open = ext4_file_open, .release = ext4_release_file, .fsync = ext4_sync_file, - .get_unmapped_area = thp_get_unmapped_area, - .splice_read = ext4_file_splice_read, - .splice_write = iter_file_splice_write, - .fallocate = ext4_fallocate, - .fop_flags = FOP_MMAP_SYNC | FOP_BUFFER_RASYNC | - FOP_DIO_PARALLEL_WRITE | - FOP_DONTCACHE, }; +/* U-Boot simplified inode operations */ const struct inode_operations ext4_file_inode_operations = { .setattr = ext4_setattr, .getattr = ext4_file_getattr, .listxattr = ext4_listxattr, - .get_inode_acl = ext4_get_acl, - .set_acl = ext4_set_acl, .fiemap = ext4_fiemap, - .fileattr_get = ext4_fileattr_get, - .fileattr_set = ext4_fileattr_set, }; diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c index f452357953e..b378eab97a3 100644 --- a/fs/ext4l/stub.c +++ b/fs/ext4l/stub.c @@ -236,6 +236,11 @@ int ext4_xattr_set(struct inode *inode, int name_index, const char *name, return -1; } +ssize_t ext4_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) +{ + return 0; +} + /* * Stubs for orphan.c */ @@ -414,8 +419,8 @@ int ext4_find_inline_data_nolock(struct inode *inode) /* File and inode operations symbols */ -char ext4_file_inode_operations; -char ext4_file_operations; +/* ext4_file_inode_operations is now in file.c */ +/* ext4_file_operations is now in file.c */ char ext4_dir_inode_operations; /* ext4_dir_operations is now in dir.c */ char ext4_special_inode_operations; @@ -485,10 +490,7 @@ ssize_t generic_read_dir(struct file *f, char *buf, size_t count, loff_t *ppos) /* __ext4_error_file is now in super.c */ -loff_t ext4_llseek(struct file *file, loff_t offset, int whence) -{ - return 0; -} +/* ext4_llseek is now in file.c */ int ext4_htree_fill_tree(struct file *dir_file, unsigned long long pos, unsigned long long start_hash, diff --git a/include/linux/fs.h b/include/linux/fs.h index 0af81af5644..ae34b1f7356 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -27,6 +27,26 @@ typedef unsigned int fmode_t; #define FMODE_READ ((__force fmode_t)(1 << 0)) #define FMODE_WRITE ((__force fmode_t)(1 << 1)) #define FMODE_LSEEK ((__force fmode_t)(1 << 2)) +#define FMODE_NOWAIT ((__force fmode_t)(1 << 20)) +#define FMODE_CAN_ODIRECT ((__force fmode_t)(1 << 21)) +#define FMODE_CAN_ATOMIC_WRITE ((__force fmode_t)(1 << 22)) + +/* Seek constants */ +#ifndef SEEK_HOLE +#define SEEK_HOLE 4 +#define SEEK_DATA 3 +#endif + +/* vfsmount - mount point */ +struct vfsmount { + struct dentry *mnt_root; +}; + +/* path - pathname components */ +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; /* Buffer operations are in buffer_head.h */ @@ -76,6 +96,7 @@ struct file { struct address_space *f_mapping; void *private_data; struct file_ra_state f_ra; + struct path f_path; }; /* Get inode from file */ diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 3bd4070cfdb..a426cf35f40 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -46,6 +46,14 @@ struct vm_fault; /* Additional iomap flags */ #define IOMAP_F_ATOMIC_BIO (1U << 6) +/* iomap DIO end_io flags */ +#define IOMAP_DIO_UNWRITTEN (1 << 0) +#define IOMAP_DIO_COW (1 << 1) + +/* iomap_dio_rw flags */ +#define IOMAP_DIO_FORCE_WAIT (1 << 0) +#define IOMAP_DIO_OVERWRITE_ONLY (1 << 1) + struct iomap { u64 addr; loff_t offset; -- 2.43.0