Switch over to device special files for implementing devfs. With this we
can drop the current devfs implementation as a filesystem driver.

Signed-off-by: Sascha Hauer <[email protected]>
---
 common/startup.c |   2 +-
 fs/devfs-core.c  |  35 +++++++++++
 fs/devfs.c       | 174 +------------------------------------------------------
 include/driver.h |   1 +
 4 files changed, 39 insertions(+), 173 deletions(-)

diff --git a/common/startup.c b/common/startup.c
index 
dfea8394fdee67f53cb608aea882d20151cc9c61..ba3bb79c861aaa9268121ee6868399fcce8ec36c
 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -60,7 +60,7 @@ static int mount_root(void)
        mkdir("/dev", 0);
        mkdir("/tmp", 0);
        mkdir("/mnt", 0);
-       mount("none", "devfs", "/dev", NULL);
+       devfs_init();
 
        if (IS_ENABLED(CONFIG_FS_EFIVARFS) && efi_is_payload()) {
                mkdir("/efivars", 0);
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 
467aa51c858a8bde6ab4e17cc4c838b989606486..3a5667b9f723fa718453bdc58827f4b760f3565a
 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -458,6 +458,39 @@ static void cdev_free(struct cdev *cdev)
        free(cdev);
 }
 
+static bool devfs_initialized;
+
+static void devfs_mknod(struct cdev *cdev)
+{
+       char *path;
+       int ret;
+
+       if (!devfs_initialized)
+               return;
+
+       path = xasprintf("/dev/%s", cdev->name);
+
+       if (cdev->link)
+               ret = symlink(cdev->link->name, path);
+       else
+               ret = mknod(path, S_IFCHR | 0600, cdev->name);
+
+       free(path);
+
+       if (ret)
+               pr_err("Failed to create /dev/%s: %pe\n", cdev->name, 
ERR_PTR(ret));
+}
+
+void devfs_init(void)
+{
+       struct cdev *cdev;
+
+       devfs_initialized = true;
+
+       for_each_cdev(cdev)
+               devfs_mknod(cdev);
+}
+
 int devfs_create(struct cdev *new)
 {
        struct cdev *cdev;
@@ -479,6 +512,8 @@ int devfs_create(struct cdev *new)
        if (new->link)
                list_add_tail(&new->link_entry, &new->link->links);
 
+       devfs_mknod(new);
+
        return 0;
 }
 
diff --git a/fs/devfs.c b/fs/devfs.c
index 
a48c6452697b47cbd3ffc6f993230e7993e565fe..061fbf5d2ffe11671c13ee5bd2cc315c378bb86f
 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -29,6 +29,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd-abi.h>
 #include <block.h>
+#include <stringlist.h>
 
 struct devfs_inode {
        struct inode inode;
@@ -143,41 +144,6 @@ static int devfs_truncate(struct file *f, loff_t size)
        return cdev_truncate(cdev, size);
 }
 
-static struct inode *devfs_alloc_inode(struct super_block *sb)
-{
-       struct devfs_inode *node;
-
-       node = xzalloc(sizeof(*node));
-       if (!node)
-               return NULL;
-
-       return &node->inode;
-}
-
-static void devfs_destroy_inode(struct inode *inode)
-{
-       struct devfs_inode *node = container_of(inode, struct devfs_inode, 
inode);
-
-       free(node);
-}
-
-static int devfs_iterate(struct file *file, struct dir_context *ctx)
-{
-       struct cdev *cdev;
-
-       dir_emit_dots(file, ctx);
-
-       for_each_cdev(cdev) {
-               dir_emit(ctx, cdev->name, strlen(cdev->name),
-                               1 /* FIXME */, DT_REG);
-       }
-
-        return 0;
-}
-
-static const struct inode_operations devfs_file_inode_operations;
-static const struct file_operations devfs_dir_operations;
-static const struct inode_operations devfs_dir_inode_operations;
 static const struct file_operations devfs_file_operations = {
        .open = devfs_open,
        .release = devfs_close,
@@ -197,141 +163,5 @@ void init_special_inode(struct inode *inode, umode_t 
mode, const char *cdevname)
 {
        inode->i_mode = mode;
        inode->i_fop = &devfs_file_operations;
-       inode->cdevname = strdup(cdevname);
-}
-
-static int devfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
-{
-       struct devfs_inode *dinode;
-       struct inode *inode;
-       struct cdev *cdev;
-
-       cdev = cdev_by_name(dentry->name);
-       if (!cdev)
-               return -ENOENT;
-
-       inode = d_inode(dentry);
-       if (!inode)
-               return 0;
-
-       dinode = container_of(inode, struct devfs_inode, inode);
-
-       if (dinode->cdev != cdev)
-               return 0;
-
-       return 1;
+       inode->cdevname = xstrdup(cdevname);
 }
-
-static const struct dentry_operations devfs_dentry_operations = {
-       .d_revalidate = devfs_lookup_revalidate,
-};
-
-static struct inode *devfs_get_inode(struct super_block *sb, const struct 
inode *dir,
-                                     umode_t mode)
-{
-       struct inode *inode = new_inode(sb);
-
-       if (!inode)
-               return NULL;
-
-       inode->i_ino = get_next_ino();
-       inode->i_mode = mode;
-
-       switch (mode & S_IFMT) {
-       default:
-               return NULL;
-       case S_IFCHR:
-       case S_IFBLK:
-               inode->i_op = &devfs_file_inode_operations;
-               inode->i_fop = &devfs_file_operations;
-               break;
-       case S_IFDIR:
-               inode->i_op = &devfs_dir_inode_operations;
-               inode->i_fop = &devfs_dir_operations;
-               inc_nlink(inode);
-               break;
-       }
-
-       return inode;
-}
-
-static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry,
-                                  unsigned int flags)
-{
-       struct devfs_inode *dinode;
-       struct inode *inode;
-       struct cdev *cdev;
-       umode_t mode;
-
-       cdev = cdev_by_name(dentry->name);
-       if (!cdev)
-               return ERR_PTR(-ENOENT);
-
-       mode = cdev_get_block_device(cdev) ? S_IFBLK : S_IFCHR;
-
-       inode = devfs_get_inode(dir->i_sb, dir, mode);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
-
-       if (cdev->ops->write)
-               inode->i_mode |= S_IWUSR;
-       if (cdev->ops->read)
-               inode->i_mode |= S_IRUSR;
-
-       dinode = container_of(inode, struct devfs_inode, inode);
-
-       inode->i_size = cdev->size;
-       dinode->cdev = cdev;
-
-       d_add(dentry, inode);
-
-       return NULL;
-}
-
-static const struct file_operations devfs_dir_operations = {
-       .iterate = devfs_iterate,
-};
-
-static const struct inode_operations devfs_dir_inode_operations =
-{
-       .lookup = devfs_lookup,
-};
-
-static const struct super_operations devfs_ops = {
-       .alloc_inode = devfs_alloc_inode,
-       .destroy_inode = devfs_destroy_inode,
-};
-
-static int devfs_probe(struct device *dev)
-{
-       struct inode *inode;
-       struct fs_device *fsdev = dev_to_fs_device(dev);
-       struct super_block *sb = &fsdev->sb;
-
-       sb->s_op = &devfs_ops;
-       sb->s_d_op = &devfs_dentry_operations;
-
-       inode = devfs_get_inode(sb, NULL, S_IFDIR);
-       sb->s_root = d_make_root(inode);
-
-       return 0;
-}
-
-static void devfs_delete(struct device *dev)
-{
-}
-
-static struct fs_driver devfs_driver = {
-       .drv = {
-               .probe  = devfs_probe,
-               .remove = devfs_delete,
-               .name = "devfs",
-       }
-};
-
-static int devfs_init(void)
-{
-       return register_fs_driver(&devfs_driver);
-}
-
-coredevice_initcall(devfs_init);
diff --git a/include/driver.h b/include/driver.h
index 
0c7a75b3d5632fdbde65ac52667e3bdee325dcf2..802917f1c20727272364d094552e4e5b40a6165b
 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -459,6 +459,7 @@ static inline const char *cdev_name(struct cdev *cdev)
        return cdev ? cdev->name : NULL;
 }
 
+void devfs_init(void);
 int devfs_create(struct cdev *);
 int devfs_create_link(struct cdev *, const char *name);
 int devfs_create_link_node(struct cdev *cdev, const char *name,

-- 
2.47.3


Reply via email to