[Concept,03/10] ext4l: Add symlink.c to build

Message ID 20251221113820.812060-4-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 symlink.c which provides symlink inode operations.

Changes needed:
- Add ext4_uboot.h include to symlink.c
- Add delayed_call struct and set_delayed_call macro
- Add kfree_link definition
- Add nd_terminate_link helper function
- Add get_link member to inode_operations struct
- Add simple_get_link function for fast symlinks
- Add i_link field to struct inode
- Add fscrypt_get_symlink and fscrypt_symlink_getattr stubs
- Add ext4_read_inline_link stub
- Remove ext4_symlink_inode_operations and
  ext4_fast_symlink_inode_operations stubs from stub.c

Drop some duplicate declarations in ext4_uboot.h

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

 fs/ext4l/Makefile     |  4 +--
 fs/ext4l/ext4_uboot.h | 77 ++++++++++++++++++++++++++++++-------------
 fs/ext4l/file.c       | 15 +++++----
 fs/ext4l/stub.c       | 15 +++++----
 fs/ext4l/symlink.c    |  7 ++--
 5 files changed, 78 insertions(+), 40 deletions(-)
  

Patch

diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile
index 96caa289be0..fe6d9ccafe8 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 dir.o ext4_jbd2.o extents.o \
 		extents_status.o file.o fsync.o hash.o ialloc.o \
-		indirect.o inode.o \
-		super.o xattr_hurd.o xattr_trusted.o \
+		indirect.o inode.o super.o symlink.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 0f0e9c91a12..83a714f78a0 100644
--- a/fs/ext4l/ext4_uboot.h
+++ b/fs/ext4l/ext4_uboot.h
@@ -816,6 +816,7 @@  struct inode {
 	const struct file_operations *i_fop;
 	atomic_t i_writecount;		/* Count of writers */
 	struct rw_semaphore i_rwsem;	/* inode lock */
+	const char *i_link;		/* Symlink target for fast symlinks */
 };
 
 /* Inode time accessors */
@@ -916,6 +917,16 @@  static inline u64 fscrypt_fname_siphash(const struct inode *dir,
 #define WARN_ON_ONCE(cond) ({ (void)(cond); 0; })
 #define WARN_ON(cond) ({ (void)(cond); 0; })
 
+/* strtomem_pad - copy string to fixed-size buffer with padding */
+#define strtomem_pad(dest, src, pad) do { \
+	size_t _len = strlen(src); \
+	if (_len >= sizeof(dest)) \
+		_len = sizeof(dest); \
+	memcpy(dest, src, _len); \
+	if (_len < sizeof(dest)) \
+		memset((char *)(dest) + _len, (pad), sizeof(dest) - _len); \
+} while (0)
+
 /* Memory weight - count set bits */
 static inline unsigned long memweight(const void *ptr, size_t bytes)
 {
@@ -980,6 +991,14 @@  static inline unsigned long memweight(const void *ptr, size_t bytes)
 #define file_modified(file)		({ (void)(file); 0; })
 #define file_accessed(file)		do { (void)(file); } while (0)
 
+/* Generic file operations - stubs for file.c */
+#define generic_file_read_iter(iocb, to)	({ (void)(iocb); (void)(to); 0L; })
+#define generic_write_checks(iocb, from)	({ (void)(iocb); (void)(from); 0L; })
+#define generic_perform_write(iocb, from)	({ (void)(iocb); (void)(from); 0L; })
+#define generic_write_sync(iocb, count)		({ (void)(iocb); (count); })
+#define generic_atomic_write_valid(iocb, from)	({ (void)(iocb); (void)(from); 0; })
+#define vfs_setpos(file, offset, maxsize)	({ (void)(file); (void)(maxsize); (offset); })
+
 /* Security checks - no security in U-Boot */
 #define IS_NOSEC(inode)			(1)
 
@@ -1295,6 +1314,7 @@  typedef unsigned int projid_t;
 /* Dentry operations - stubs */
 #define d_find_any_alias(i)			({ (void)(i); (struct dentry *)NULL; })
 #define dget_parent(d)				({ (void)(d); (struct dentry *)NULL; })
+#define dput(d)					do { (void)(d); } while (0)
 
 /* Sync operations - stubs */
 #define sync_mapping_buffers(m)			({ (void)(m); 0; })
@@ -1393,6 +1413,7 @@  static inline char *d_path(const struct path *path, char *buf, int buflen)
 #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)
+#define filemap_splice_read(i, p, pi, l, f)	({ (void)(i); (void)(p); (void)(pi); (void)(l); (void)(f); 0L; })
 
 /* Buffer operations - additional */
 #define getblk_unmovable(bd, b, s)		((struct buffer_head *)NULL)
@@ -1512,15 +1533,6 @@  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; })
@@ -1578,8 +1590,30 @@  struct file_operations {
 	int (*release)(struct inode *, struct file *);
 };
 
+/* delayed_call - for delayed freeing of symlink data */
+typedef void (*delayed_call_func_t)(const void *);
+struct delayed_call {
+	delayed_call_func_t fn;
+	const void *arg;
+};
+
+#define set_delayed_call(dc, func, data) do { \
+	(dc)->fn = (func); \
+	(dc)->arg = (data); \
+} while (0)
+
+#define kfree_link		kfree
+
+/* nd_terminate_link - terminate symlink string */
+static inline void nd_terminate_link(void *name, loff_t len, int maxlen)
+{
+	((char *)name)[min_t(loff_t, len, maxlen)] = '\0';
+}
+
 /* inode_operations - for file and directory operations */
 struct inode_operations {
+	const char *(*get_link)(struct dentry *, struct inode *,
+				struct delayed_call *);
 	int (*getattr)(struct mnt_idmap *, const struct path *,
 		       struct kstat *, u32, unsigned int);
 	ssize_t (*listxattr)(struct dentry *, char *, size_t);
@@ -1596,6 +1630,18 @@  struct inode_operations {
 /* file open helper */
 #define simple_open(i, f)		({ (void)(i); (void)(f); 0; })
 
+/* simple_get_link - for fast symlinks stored in inode */
+static inline const char *simple_get_link(struct dentry *dentry,
+					  struct inode *inode,
+					  struct delayed_call *callback)
+{
+	return inode->i_link;
+}
+
+/* fscrypt symlink stubs */
+#define fscrypt_get_symlink(i, c, m, d)	({ (void)(i); (void)(c); (void)(m); (void)(d); ERR_PTR(-EOPNOTSUPP); })
+#define fscrypt_symlink_getattr(p, s)	({ (void)(p); (void)(s); 0; })
+
 /*
  * Additional stubs for super.c
  */
@@ -2118,23 +2164,10 @@  void set_task_ioprio(void *task, int ioprio);
 /* Dentry operations - declarations for stub.c */
 void generic_set_sb_d_ops(struct super_block *sb);
 struct dentry *d_make_root(struct inode *inode);
-void dput(void *dentry);
 
 /* String operations - declarations for stub.c */
 char *strreplace(const char *str, char old, char new);
 
-/* strtomem_pad - copy string with padding (Linux kernel macro) */
-#define strtomem_pad(dest, src, pad) do { \
-	const char *__src = (src); \
-	size_t __len = strlen(__src); \
-	if (__len >= sizeof(dest)) { \
-		memcpy((dest), __src, sizeof(dest)); \
-	} else { \
-		memcpy((dest), __src, __len); \
-		memset((char *)(dest) + __len, (pad), sizeof(dest) - __len); \
-	} \
-} while (0)
-
 /* Ratelimit - declaration for stub.c */
 void ratelimit_state_init(void *rs, int interval, int burst);
 
diff --git a/fs/ext4l/file.c b/fs/ext4l/file.c
index b4127dbe913..8cbc8c5f785 100644
--- a/fs/ext4l/file.c
+++ b/fs/ext4l/file.c
@@ -119,7 +119,8 @@  static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
 }
 #endif
 
-static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t __maybe_unused ext4_file_read_iter(struct kiocb *iocb,
+						  struct iov_iter *to)
 {
 	struct inode *inode = file_inode(iocb->ki_filp);
 
@@ -139,9 +140,11 @@  static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 	return generic_file_read_iter(iocb, to);
 }
 
-static ssize_t ext4_file_splice_read(struct file *in, loff_t *ppos,
-				     struct pipe_inode_info *pipe,
-				     size_t len, unsigned int flags)
+static ssize_t __maybe_unused ext4_file_splice_read(struct file *in,
+						    loff_t *ppos,
+						    struct pipe_inode_info *pipe,
+						    size_t len,
+						    unsigned int flags)
 {
 	struct inode *inode = file_inode(in);
 
@@ -682,7 +685,7 @@  out:
 }
 #endif
 
-static ssize_t
+static ssize_t __maybe_unused
 ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
 	int ret;
@@ -796,7 +799,7 @@  static const struct vm_operations_struct ext4_file_vm_ops = {
 	.page_mkwrite   = ext4_page_mkwrite,
 };
 
-static int ext4_file_mmap_prepare(struct vm_area_desc *desc)
+static int __maybe_unused ext4_file_mmap_prepare(struct vm_area_desc *desc)
 {
 	int ret;
 	struct file *file = desc->file;
diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c
index 4dac514340c..2c15ffce5b1 100644
--- a/fs/ext4l/stub.c
+++ b/fs/ext4l/stub.c
@@ -429,8 +429,8 @@  int ext4_find_inline_data_nolock(struct inode *inode)
 char ext4_dir_inode_operations;
 /* ext4_dir_operations is now in dir.c */
 char ext4_special_inode_operations;
-char ext4_symlink_inode_operations;
-char ext4_fast_symlink_inode_operations;
+/* ext4_symlink_inode_operations is now in symlink.c */
+/* ext4_fast_symlink_inode_operations is now in symlink.c */
 
 
 /* ext4_update_dynamic_rev is now in super.c */
@@ -485,6 +485,12 @@  void jbd2_journal_init_jbd_inode(void *jinode, struct inode *inode)
 {
 }
 
+/* symlink.c stub */
+void *ext4_read_inline_link(struct inode *inode)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
 /*
  * Stubs for dir.c
  */
@@ -870,10 +876,7 @@  int ext4_register_sysfs(void *sb)
 	return 0;
 }
 
-/* dentry put */
-void dput(void *dentry)
-{
-}
+/* dput - now provided as macro in ext4_uboot.h */
 
 /* timer_delete_sync is now a macro in linux/timer.h */
 
diff --git a/fs/ext4l/symlink.c b/fs/ext4l/symlink.c
index 645240cc022..2e4d0942a3b 100644
--- a/fs/ext4l/symlink.c
+++ b/fs/ext4l/symlink.c
@@ -18,8 +18,7 @@ 
  *  ext4 symlink handling code
  */
 
-#include <linux/fs.h>
-#include <linux/namei.h>
+#include "ext4_uboot.h"
 #include "ext4.h"
 #include "xattr.h"
 
@@ -65,9 +64,9 @@  static int ext4_encrypted_symlink_getattr(struct mnt_idmap *idmap,
 	return fscrypt_symlink_getattr(path, stat);
 }
 
-static void ext4_free_link(void *bh)
+static void ext4_free_link(const void *bh)
 {
-	brelse(bh);
+	brelse((struct buffer_head *)bh);
 }
 
 static const char *ext4_get_link(struct dentry *dentry, struct inode *inode,