[Concept,02/16] fs: Move generic VFS stubs out of ext4l
Commit Message
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(-)
@@ -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 */
@@ -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();
+ }
+ }
+}