[Concept,02/16] fs: Move generic VFS stubs out of ext4l

Message ID 20260421183511.2044469-3-sjg@u-boot.org
State New
Headers
Series efi-x86: Boot Ubuntu live ISOs via U-Boot + BLS, end to end |

Commit Message

Simon Glass April 21, 2026, 6:34 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

The Linux-port shims alloc_inode_sb(), free_page(), sb_set_blocksize(),
d_make_root() and iput() live in fs/ext4l/stub.c, which is only built
when CONFIG_FS_EXT4L is set. Nothing in those five functions is
ext4-specific; they are also called by code under fs/isofs, so building
U-Boot with CONFIG_FS_ISOFS=y and CONFIG_FS_EXT4L=n produces an image
with five unresolved externals. Calling into isofs at runtime jumps
through a NULL function pointer and triggers a #UD on x86.

Move the five functions into fs/linux_fs.c, which is already compiled
when CONFIG_FS_LINUX is set (auto-selected by FS_ISOFS or FS_EXT4L).
Also add <linux/dcache.h> for struct dentry - the behaviour is
unchanged for ext4l-only builds.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 fs/ext4l/stub.c | 74 +++-------------------------------------
 fs/linux_fs.c   | 89 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 70 deletions(-)
  

Patch

diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c
index 6fe8398623e..df2a72bc731 100644
--- a/fs/ext4l/stub.c
+++ b/fs/ext4l/stub.c
@@ -337,11 +337,7 @@  int inode_generic_drop(struct inode *inode)
 	return 0;
 }
 
-void *alloc_inode_sb(struct super_block *sb, struct kmem_cache *cache,
-		     gfp_t gfp)
-{
-	return kmem_cache_alloc(cache, gfp);
-}
+/* alloc_inode_sb() is now in fs/linux_fs.c */
 
 /* inode_set_iversion is now a macro in linux/iversion.h */
 
@@ -381,10 +377,7 @@  unsigned long get_zeroed_page(gfp_t gfp)
 	return (unsigned long)p;
 }
 
-void free_page(unsigned long addr)
-{
-	free((void *)addr);
-}
+/* free_page() is now in fs/linux_fs.c */
 
 /* Trace stubs */
 void trace_ext4_error(struct super_block *sb, const char *func, unsigned int line)
@@ -460,19 +453,7 @@  void fs_put_dax(void *dax, void *holder)
 {
 }
 
-/* Block size */
-int sb_set_blocksize(struct super_block *sb, int size)
-{
-	/* Validate block size */
-	if (size != 1024 && size != 2048 && size != 4096)
-		return 0;
-
-	/* Update superblock fields */
-	sb->s_blocksize = size;
-	sb->s_blocksize_bits = ffs(size) - 1;
-
-	return size;
-}
+/* sb_set_blocksize() is now in fs/linux_fs.c */
 
 /* strscpy_pad is now a macro in linux/string.h */
 /* kmemdup_nul is now in lib/string.c */
@@ -501,54 +482,7 @@  void generic_set_sb_d_ops(struct super_block *sb)
 {
 }
 
-/**
- * d_make_root() - Create a root dentry for an inode
- * @inode: Inode to create dentry for
- * Return: Allocated dentry or NULL on failure
- */
-struct dentry *d_make_root(struct inode *inode)
-{
-	struct dentry *de;
-
-	if (!inode)
-		return NULL;
-
-	de = kzalloc(sizeof(struct dentry), GFP_KERNEL);
-	if (!de) {
-		iput(inode);
-		return NULL;
-	}
-
-	de->d_inode = inode;
-	de->d_sb = inode->i_sb;
-	de->d_name.name = "/";
-	de->d_name.len = 1;
-
-	return de;
-}
-
-/**
- * iput() - Release a reference to an inode
- * @inode: Inode to release
- *
- * Decrements the inode reference count. When the reference count reaches
- * zero and the inode has no links, the inode is evicted (freed).
- */
-void iput(struct inode *inode)
-{
-	if (!inode)
-		return;
-
-	if (atomic_dec_and_test(&inode->i_count)) {
-		/* Last reference - check if inode should be evicted */
-		if (inode->i_nlink == 0 && inode->i_sb &&
-		    inode->i_sb->s_op && inode->i_sb->s_op->evict_inode) {
-			inode->i_sb->s_op->evict_inode(inode);
-			/* Sync dirty buffers after eviction */
-			bh_cache_sync();
-		}
-	}
-}
+/* d_make_root() and iput() are now in fs/linux_fs.c */
 
 /* percpu_init_rwsem is now in linux/percpu.h */
 
diff --git a/fs/linux_fs.c b/fs/linux_fs.c
index 04f4c551f0b..db2b3b3942a 100644
--- a/fs/linux_fs.c
+++ b/fs/linux_fs.c
@@ -22,6 +22,7 @@ 
 #include <linux/stat.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/dcache.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/bio.h>
@@ -657,3 +658,91 @@  const struct file_operations generic_ro_fops = {
 
 const struct inode_operations page_symlink_inode_operations = {
 };
+
+/**
+ * alloc_inode_sb() - Allocate an inode associated with a super block
+ * @sb: Super block the inode will belong to
+ * @cache: kmem_cache to allocate from
+ * @gfp: Allocation flags
+ * Return: Newly allocated inode, or NULL on failure
+ */
+void *alloc_inode_sb(struct super_block *sb, struct kmem_cache *cache,
+		     gfp_t gfp)
+{
+	return kmem_cache_alloc(cache, gfp);
+}
+
+/**
+ * free_page() - Free a single page previously obtained via get_zeroed_page()
+ * @addr: Address returned by get_zeroed_page()
+ */
+void free_page(unsigned long addr)
+{
+	free((void *)addr);
+}
+
+/**
+ * sb_set_blocksize() - Validate and record the block size on a super block
+ * @sb: Super block to update
+ * @size: Block size in bytes (must be 1024, 2048 or 4096)
+ * Return: @size on success, 0 on invalid block size
+ */
+int sb_set_blocksize(struct super_block *sb, int size)
+{
+	if (size != 1024 && size != 2048 && size != 4096)
+		return 0;
+
+	sb->s_blocksize = size;
+	sb->s_blocksize_bits = ffs(size) - 1;
+
+	return size;
+}
+
+/**
+ * d_make_root() - Create a root dentry for an inode
+ * @inode: Inode to create a dentry for
+ * Return: Allocated dentry, or NULL on failure (the inode is released on
+ *	failure via iput())
+ */
+struct dentry *d_make_root(struct inode *inode)
+{
+	struct dentry *de;
+
+	if (!inode)
+		return NULL;
+
+	de = kzalloc(sizeof(*de), GFP_KERNEL);
+	if (!de) {
+		iput(inode);
+		return NULL;
+	}
+
+	de->d_inode = inode;
+	de->d_sb = inode->i_sb;
+	de->d_name.name = "/";
+	de->d_name.len = 1;
+
+	return de;
+}
+
+/**
+ * iput() - Release a reference to an inode
+ * @inode: Inode to release
+ *
+ * Decrement the inode reference count. When the reference count reaches
+ * zero and the inode has no links, evict the inode via its super block
+ * operations and flush any dirty buffers.
+ */
+void iput(struct inode *inode)
+{
+	if (!inode)
+		return;
+
+	if (atomic_dec_and_test(&inode->i_count)) {
+		if (inode->i_nlink == 0 && inode->i_sb &&
+		    inode->i_sb->s_op && inode->i_sb->s_op->evict_inode) {
+			inode->i_sb->s_op->evict_inode(inode);
+			bh_cache_sync();
+		}
+	}
+}