[Concept,04/10] ext4l: Add namei.c to build

Message ID 20251221113820.812060-5-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 directory name operations (lookup, create, link, unlink, symlink,
mkdir, rmdir, mknod, rename, tmpfile) to the ext4l filesystem.

Add stubs for:
- fscrypt name operations (match, prepare symlink/link/rename)
- Dentry operations (d_splice_alias, d_obtain_alias, d_instantiate, etc)
- Fast commit tracking functions
- Inline directory functions
- Fileattr get/set

Extend inode_operations struct with directory operation members.
Add permission mode constants (S_IRWXUGO) and rename flags.

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 |  70 +++++++++++++++++++++++++++-
 fs/ext4l/namei.c      |  15 +-----
 fs/ext4l/stub.c       | 105 ++++++++++++++++++++++++++++++++++++------
 4 files changed, 162 insertions(+), 30 deletions(-)
  

Patch

diff --git a/fs/ext4l/Makefile b/fs/ext4l/Makefile
index fe6d9ccafe8..363cd913336 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 symlink.o \
+		indirect.o inode.o namei.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 83a714f78a0..c8c8b3c702d 100644
--- a/fs/ext4l/ext4_uboot.h
+++ b/fs/ext4l/ext4_uboot.h
@@ -124,6 +124,7 @@  typedef struct { unsigned int val; } kprojid_t;
 
 #define make_kprojid(ns, id)	((kprojid_t){ .val = (id) })
 #define from_kprojid(ns, kprojid)	((kprojid).val)
+#define projid_eq(a, b)		((a).val == (b).val)
 
 /* kobject - stub */
 struct kobject {
@@ -396,7 +397,7 @@  extern struct user_namespace init_user_ns;
 #define insert_inode_locked(inode)		(0)
 #define unlock_new_inode(inode)			do { } while (0)
 #define clear_nlink(inode)			do { } while (0)
-#define IS_DIRSYNC(inode)			(0)
+#define IS_DIRSYNC(inode)			({ (void)(inode); 0; })
 
 /* fscrypt stubs */
 #define fscrypt_prepare_new_inode(dir, i, e)	({ (void)(dir); (void)(i); (void)(e); 0; })
@@ -548,6 +549,7 @@  struct dentry {
 	struct qstr d_name;
 	struct inode *d_inode;
 	struct super_block *d_sb;
+	struct dentry *d_parent;
 };
 
 /* vm_fault_t - stub */
@@ -681,6 +683,18 @@  static inline int bdev_read_only(struct block_device *bdev)
 #define S_CASEFOLD	128
 #define S_VERITY	256
 
+/* Permission mode constants */
+#define S_IRWXUGO	(S_IRWXU | S_IRWXG | S_IRWXO)
+
+/* Whiteout mode for overlayfs */
+#define WHITEOUT_DEV	0
+#define WHITEOUT_MODE	0
+
+/* Rename flags */
+#define RENAME_NOREPLACE	(1 << 0)
+#define RENAME_EXCHANGE		(1 << 1)
+#define RENAME_WHITEOUT		(1 << 2)
+
 /* Inode dirty state flags */
 #define I_DIRTY_TIME		(1 << 3)
 
@@ -851,6 +865,9 @@  static inline void simple_inode_init_ts(struct inode *inode)
 
 #define QSTR_INIT(n, l) { .name = (const unsigned char *)(n), .len = (l) }
 
+/* dotdot_name for ".." lookups */
+static const struct qstr dotdot_name = QSTR_INIT("..", 2);
+
 /*
  * Hash info structure - defined in ext4.h.
  * Only defined here for files that don't include ext4.h (like hash.c)
@@ -1036,6 +1053,10 @@  static inline vm_fault_t filemap_map_pages(struct vm_fault *vmf,
 /* IS_SYNC macro */
 #define IS_SYNC(inode)			(0)
 
+/* Case-folding stubs - not supported in U-Boot */
+#define sb_no_casefold_compat_fallback(sb)	({ (void)(sb); 1; })
+#define generic_ci_validate_strict_name(d, n)	({ (void)(d); (void)(n); 1; })
+
 /* in_range helper - check if value is in range [start, start+len) */
 static inline int in_range(unsigned long val, unsigned long start,
 			   unsigned long len)
@@ -1310,11 +1331,21 @@  typedef unsigned int projid_t;
 #define trace_ext4_journalled_write_end(...)	do { } while (0)
 #define trace_ext4_sync_file_enter(...)		do { } while (0)
 #define trace_ext4_sync_file_exit(...)		do { } while (0)
+#define trace_ext4_unlink_enter(...)		do { } while (0)
+#define trace_ext4_unlink_exit(...)		do { } while (0)
 
 /* 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)
+#define d_splice_alias(i, d)			({ (void)(i); (void)(d); (struct dentry *)NULL; })
+#define d_obtain_alias(i)			({ (void)(i); (struct dentry *)NULL; })
+#define d_instantiate_new(d, i)			do { (void)(d); (void)(i); } while (0)
+#define d_instantiate(d, i)			do { (void)(d); (void)(i); } while (0)
+#define d_tmpfile(f, i)				do { (void)(f); (void)(i); } while (0)
+#define d_invalidate(d)				do { (void)(d); } while (0)
+#define finish_open_simple(f, e)		(e)
+#define ihold(i)				do { (void)(i); } while (0)
 
 /* Sync operations - stubs */
 #define sync_mapping_buffers(m)			({ (void)(m); 0; })
@@ -1435,6 +1466,22 @@  static inline char *d_path(const struct path *path, char *buf, int buflen)
 #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)
+#define fscrypt_match_name(f, n, l)		({ (void)(f); (void)(n); (void)(l); 1; })
+#define fscrypt_has_permitted_context(p, c)	({ (void)(p); (void)(c); 1; })
+#define fscrypt_is_nokey_name(d)		({ (void)(d); 0; })
+#define fscrypt_prepare_symlink(d, s, l, m, dl)	({ (void)(d); (void)(s); (void)(l); (void)(m); (void)(dl); 0; })
+#define fscrypt_encrypt_symlink(i, s, l, d)	({ (void)(i); (void)(s); (void)(l); (void)(d); 0; })
+#define fscrypt_prepare_link(o, d, n)		({ (void)(o); (void)(d); (void)(n); 0; })
+#define fscrypt_prepare_rename(od, ode, nd, nde, f) ({ (void)(od); (void)(ode); (void)(nd); (void)(nde); (void)(f); 0; })
+
+/* fscrypt_name - stub structure for encrypted filenames */
+struct fscrypt_name {
+	const struct qstr *usr_fname;
+	struct fscrypt_str disk_name;
+	u32 hash;
+	u32 minor_hash;
+	bool is_nokey_name;
+};
 
 /* fsverity stubs */
 #define fsverity_prepare_setattr(d, a)		({ (void)(d); (void)(a); 0; })
@@ -1511,6 +1558,8 @@  static inline unsigned int i_gid_read(const struct inode *inode)
 /* 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 inc_nlink(i)			do { (i)->i_nlink++; } while (0)
+#define drop_nlink(i)			do { (i)->i_nlink--; } 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)
@@ -1612,8 +1661,10 @@  static inline void nd_terminate_link(void *name, loff_t len, int maxlen)
 
 /* inode_operations - for file and directory operations */
 struct inode_operations {
+	/* Symlink operations */
 	const char *(*get_link)(struct dentry *, struct inode *,
 				struct delayed_call *);
+	/* Common operations */
 	int (*getattr)(struct mnt_idmap *, const struct path *,
 		       struct kstat *, u32, unsigned int);
 	ssize_t (*listxattr)(struct dentry *, char *, size_t);
@@ -1625,6 +1676,23 @@  struct inode_operations {
 	int (*fileattr_get)(struct dentry *, struct file_kattr *);
 	int (*fileattr_set)(struct mnt_idmap *, struct dentry *,
 			    struct file_kattr *);
+	/* Directory operations */
+	struct dentry *(*lookup)(struct inode *, struct dentry *, unsigned int);
+	int (*create)(struct mnt_idmap *, struct inode *, struct dentry *,
+		      umode_t, bool);
+	int (*link)(struct dentry *, struct inode *, struct dentry *);
+	int (*unlink)(struct inode *, struct dentry *);
+	int (*symlink)(struct mnt_idmap *, struct inode *, struct dentry *,
+		       const char *);
+	struct dentry *(*mkdir)(struct mnt_idmap *, struct inode *,
+				struct dentry *, umode_t);
+	int (*rmdir)(struct inode *, struct dentry *);
+	int (*mknod)(struct mnt_idmap *, struct inode *, struct dentry *,
+		     umode_t, dev_t);
+	int (*rename)(struct mnt_idmap *, struct inode *, struct dentry *,
+		      struct inode *, struct dentry *, unsigned int);
+	int (*tmpfile)(struct mnt_idmap *, struct inode *, struct file *,
+		       umode_t);
 };
 
 /* file open helper */
diff --git a/fs/ext4l/namei.c b/fs/ext4l/namei.c
index 2cd36f59c9e..7ef20d02235 100644
--- a/fs/ext4l/namei.c
+++ b/fs/ext4l/namei.c
@@ -25,24 +25,11 @@ 
  *	Theodore Ts'o, 2002
  */
 
-#include <linux/fs.h>
-#include <linux/pagemap.h>
-#include <linux/time.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/quotaops.h>
-#include <linux/buffer_head.h>
-#include <linux/bio.h>
-#include <linux/iversion.h>
-#include <linux/unicode.h>
+#include "ext4_uboot.h"
 #include "ext4.h"
 #include "ext4_jbd2.h"
-
 #include "xattr.h"
 #include "acl.h"
-
-#include <trace/events/ext4.h>
 /*
  * define how far ahead to read directories while searching them.
  */
diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c
index 2c15ffce5b1..af6efa892b5 100644
--- a/fs/ext4l/stub.c
+++ b/fs/ext4l/stub.c
@@ -426,9 +426,9 @@  int ext4_find_inline_data_nolock(struct inode *inode)
 /* File and inode operations symbols */
 /* ext4_file_inode_operations is now in file.c */
 /* ext4_file_operations is now in file.c */
-char ext4_dir_inode_operations;
+/* ext4_dir_inode_operations is now in namei.c */
 /* ext4_dir_operations is now in dir.c */
-char ext4_special_inode_operations;
+/* ext4_special_inode_operations is now in namei.c */
 /* ext4_symlink_inode_operations is now in symlink.c */
 /* ext4_fast_symlink_inode_operations is now in symlink.c */
 
@@ -503,24 +503,105 @@  ssize_t generic_read_dir(struct file *f, char *buf, size_t count, loff_t *ppos)
 
 /* 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,
-			 unsigned long long start_minor_hash,
-			 unsigned long long *next_hash)
+/* ext4_htree_fill_tree is now in namei.c */
+
+int ext4_read_inline_dir(struct file *file, void *ctx, void *f_pos)
 {
 	return 0;
 }
 
-int ext4_read_inline_dir(struct file *file, void *ctx, void *f_pos)
+struct buffer_head *ext4_find_inline_entry(struct inode *dir, void *fname,
+					   void *res_dir, int *has_inline_data)
+{
+	*has_inline_data = 0;
+	return NULL;
+}
+
+int ext4_try_add_inline_entry(void *handle, void *fname, void *dentry)
+{
+	return -ENOENT;
+}
+
+int ext4_delete_inline_entry(void *handle, struct inode *dir,
+			     void *de_del, struct buffer_head *bh,
+			     int *has_inline_data)
+{
+	*has_inline_data = 0;
+	return -ENOENT;
+}
+
+void ext4_update_final_de(void *de, int de_len, int new_de_len)
 {
-	return 0;
 }
 
-int ext4_dirblock_csum_verify(struct inode *inode, struct buffer_head *bh)
+int ext4_try_create_inline_dir(void *handle, struct inode *parent,
+			       struct inode *inode)
 {
+	return -ENOENT;
+}
+
+int empty_inline_dir(struct inode *dir, int *has_inline_data)
+{
+	*has_inline_data = 0;
 	return 1;
 }
 
+/* Inline dir stubs */
+int ext4_get_first_inline_block(struct inode *inode, void **de,
+				int *inline_size)
+{
+	return 0;
+}
+
+int ext4_inlinedir_to_tree(struct file *dir, struct inode *inode,
+			   unsigned long long start_hash,
+			   unsigned long long *next_hash,
+			   int has_inline_data)
+{
+	return 0;
+}
+
+/* Fast commit stubs */
+void ext4_fc_track_unlink(void *handle, struct dentry *dentry)
+{
+}
+
+void ext4_fc_track_link(void *handle, struct dentry *dentry)
+{
+}
+
+void ext4_fc_track_create(void *handle, struct dentry *dentry)
+{
+}
+
+void __ext4_fc_track_link(void *handle, struct inode *inode,
+			  struct dentry *dentry)
+{
+}
+
+void __ext4_fc_track_unlink(void *handle, struct inode *inode,
+			    struct dentry *dentry)
+{
+}
+
+void __ext4_fc_track_create(void *handle, struct inode *inode,
+			    struct dentry *dentry)
+{
+}
+
+/* fileattr stubs */
+int ext4_fileattr_get(struct dentry *dentry, void *fa)
+{
+	return 0;
+}
+
+int ext4_fileattr_set(void *idmap, struct dentry *dentry, void *fa)
+{
+	return 0;
+}
+
+/* ext4_dirblock_csum_verify is now in namei.c */
+
 /* ext4_ioctl is now in super.c */
 
 /* ext4_sync_file is now in fsync.c */
@@ -880,11 +961,7 @@  int ext4_register_sysfs(void *sb)
 
 /* timer_delete_sync is now a macro in linux/timer.h */
 
-/* Get parent */
-void *ext4_get_parent(void *dentry)
-{
-	return (void *)-ESTALE;
-}
+/* ext4_get_parent is now in namei.c */
 
 /* fsnotify */
 void fsnotify_sb_error(struct super_block *sb, struct inode *inode, int error)