feat: (devfs) a new filesystem for device exposure.
authorMinep <zelong56@gmail.com>
Sun, 21 Aug 2022 15:03:15 +0000 (16:03 +0100)
committerMinep <zelong56@gmail.com>
Sun, 21 Aug 2022 15:03:15 +0000 (16:03 +0100)
chore: fixes and refactorings.

lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/ds/llist.h
lunaix-os/includes/lunaix/fs/devfs.h [new file with mode: 0644]
lunaix-os/kernel/device.c [deleted file]
lunaix-os/kernel/device/devfs.c [new file with mode: 0644]
lunaix-os/kernel/device/device.c [new file with mode: 0644]
lunaix-os/kernel/fs/fs_setup.c
lunaix-os/kernel/fs/mount.c
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/k_init.c
lunaix-os/kernel/proc0.c

index 414809a233aff8aa6d69c63eb8c8feb793456b42..c0ed9896382ef901e0fb676d224187b33a033520 100644 (file)
@@ -6,31 +6,46 @@
 #include <lunaix/ds/hstr.h>
 #include <lunaix/ds/llist.h>
 
+#define DEV_MSKIF 0x00000003
+
+#define DEV_IFVOL 0x0 // volumetric (block) device
+#define DEV_IFSEQ 0x1 // sequential (character) device
+#define DEV_IFCAT 0x2 // a device category (as device groupping)
+
 typedef unsigned int dev_t;
 
 struct device
 {
-    struct llist_header dev_list;
+    struct llist_header siblings;
     struct device* parent;
     struct hstr name;
     dev_t dev_id;
+    int dev_type;
     char name_val[DEVICE_NAME_SIZE];
     void* underlay;
-    void* fs_node;
     int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
     int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
 };
 
-void
-device_init();
-
 struct device*
 device_addseq(struct device* parent, void* underlay, char* name_fmt, ...);
 
 struct device*
 device_addvol(struct device* parent, void* underlay, char* name_fmt, ...);
 
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...);
+
 void
 device_remove(struct device* dev);
 
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id);
+
+struct device*
+device_getbyname(struct llist_header* devlist, struct hstr* name);
+
+struct device*
+device_getbyoffset(struct llist_header* devlist, int pos);
+
 #endif /* __LUNAIX_DEVICE_H */
index 22e0f931b3e22fb9cad6c29963dc6f8b18b958ca..a4797c34d3f889ab9c0e970ed693607ee7953fbe 100644 (file)
@@ -67,6 +67,12 @@ llist_empty(struct llist_header* elem)
     return elem->next == elem && elem->prev == elem;
 }
 
+#define DEFINE_LLIST(name)                                                     \
+    struct llist_header name = (struct llist_header)                           \
+    {                                                                          \
+        .prev = &name, .next = &name                                           \
+    }
+
 /**
  * list_entry - get the struct for this entry
  * @ptr:       the &struct list_head pointer.
diff --git a/lunaix-os/includes/lunaix/fs/devfs.h b/lunaix-os/includes/lunaix/fs/devfs.h
new file mode 100644 (file)
index 0000000..324706c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __LUNAIX_DEVFS_H
+#define __LUNAIX_DEVFS_H
+
+void
+devfs_init();
+
+#endif /* __LUNAIX_DEVFS_H */
diff --git a/lunaix-os/kernel/device.c b/lunaix-os/kernel/device.c
deleted file mode 100644 (file)
index 017f3b3..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <klibc/stdio.h>
-#include <lunaix/device.h>
-#include <lunaix/fs/twifs.h>
-#include <lunaix/mm/valloc.h>
-
-struct llist_header dev_list;
-
-static struct twifs_node* dev_root;
-
-int
-__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
-
-int
-__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
-
-void
-device_init()
-{
-    dev_root = twifs_toplevel_node("dev", 3, 0);
-
-    llist_init_head(&dev_list);
-}
-
-struct device*
-__device_add(struct device* parent,
-             void* underlay,
-             char* name_fmt,
-             uint32_t type,
-             va_list args)
-{
-    struct device* dev = vzalloc(sizeof(struct device));
-
-    size_t strlen =
-      __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
-
-    dev->name = HSTR(dev->name_val, strlen);
-    dev->parent = parent;
-    dev->underlay = underlay;
-
-    hstr_rehash(&dev->name, HSTR_FULL_HASH);
-    llist_append(&dev_list, &dev->dev_list);
-
-    struct twifs_node* dev_node =
-      twifs_file_node(dev_root, dev->name_val, strlen, type);
-    dev_node->data = dev;
-    dev_node->ops.read = __dev_read;
-    dev_node->ops.write = __dev_write;
-
-    dev->fs_node = dev_node;
-
-    return dev;
-}
-
-struct device*
-device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
-{
-    va_list args;
-    va_start(args, name_fmt);
-
-    struct device* dev =
-      __device_add(parent, underlay, name_fmt, VFS_IFSEQDEV, args);
-
-    va_end(args);
-    return dev;
-}
-
-struct device*
-device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
-{
-    va_list args;
-    va_start(args, name_fmt);
-
-    struct device* dev =
-      __device_add(parent, underlay, name_fmt, VFS_IFVOLDEV, args);
-
-    va_end(args);
-    return dev;
-}
-
-int
-__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
-{
-    struct twifs_node* dev_node = (struct twifs_node*)inode->data;
-    struct device* dev = (struct device*)dev_node->data;
-
-    if (!dev->read) {
-        return ENOTSUP;
-    }
-    return dev->read(dev, buffer, fpos, len);
-}
-
-int
-__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
-{
-    struct twifs_node* dev_node = (struct twifs_node*)inode->data;
-    struct device* dev = (struct device*)dev_node->data;
-
-    if (!dev->write) {
-        return ENOTSUP;
-    }
-    return dev->write(dev, buffer, fpos, len);
-}
-
-void
-device_remove(struct device* dev)
-{
-    llist_delete(&dev->dev_list);
-    twifs_rm_node((struct twifs_node*)dev->fs_node);
-    vfree(dev);
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c
new file mode 100644 (file)
index 0000000..73abac7
--- /dev/null
@@ -0,0 +1,147 @@
+#include <lunaix/device.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/devfs.h>
+#include <lunaix/spike.h>
+
+extern struct v_inode_ops devfs_inode_ops;
+extern struct v_file_ops devfs_file_ops;
+
+int
+devfs_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+    assert(inode->data);
+
+    struct device* dev = (struct device*)inode->data;
+
+    if (!dev->read) {
+        return ENOTSUP;
+    }
+
+    return dev->read(dev, buffer, fpos, len);
+}
+
+int
+devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+    assert(inode->data);
+
+    struct device* dev = (struct device*)inode->data;
+
+    if (!dev->write) {
+        return ENOTSUP;
+    }
+
+    return dev->write(dev, buffer, fpos, len);
+}
+
+int
+devfs_get_itype(struct device* dev)
+{
+    int itype = VFS_IFFILE;
+    int dev_if = dev->dev_type & DEV_MSKIF;
+    if (dev_if == DEV_IFCAT) {
+        itype = VFS_IFDIR;
+    } else if (dev_if == DEV_IFVOL) {
+        itype |= VFS_IFVOLDEV;
+    } else {
+        itype |= VFS_IFSEQDEV;
+    }
+    return itype;
+}
+
+int
+devfs_mknod(struct v_dnode* dnode, struct device* dev)
+{
+    assert(dev);
+
+    struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id);
+    if (!devnod) {
+        if ((devnod = vfs_i_alloc(dnode->super_block))) {
+            devnod->id = dev->dev_id;
+            devnod->data = dev;
+            devnod->itype = devfs_get_itype(dev);
+
+            vfs_i_addhash(devnod);
+        } else {
+            return ENOMEM;
+        }
+    }
+
+    vfs_assign_inode(dnode, devnod);
+    return 0;
+}
+
+int
+devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
+{
+    struct device* dev = device_getbyname(this->data, &dnode->name);
+    if (!dev) {
+        return ENOENT;
+    }
+    return devfs_mknod(dnode, dev);
+}
+
+int
+devfs_readdir(struct v_file* file, struct dir_context* dctx)
+{
+    struct device* dev = device_getbyoffset(file->inode->data, dctx->index);
+    if (!dev) {
+        return 0;
+    }
+    dctx->read_complete_callback(
+      dctx, dev->name.value, dev->name.len, devfs_get_itype(dev));
+    return 1;
+}
+
+void
+devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
+{
+    inode->ops = &devfs_inode_ops;
+    inode->default_fops = &devfs_file_ops;
+}
+
+int
+devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
+{
+    vsb->ops.init_inode = devfs_init_inode;
+
+    struct v_inode* rootnod = vfs_i_alloc(vsb);
+
+    if (!rootnod) {
+        return ENOMEM;
+    }
+
+    rootnod->id = -1;
+    rootnod->itype = VFS_IFDIR;
+
+    vfs_i_addhash(rootnod);
+    vfs_assign_inode(mount_point, rootnod);
+
+    return 0;
+}
+
+int
+devfs_unmount(struct v_superblock* vsb)
+{
+    return 0;
+}
+
+void
+devfs_init()
+{
+    struct filesystem* fs = fsm_new_fs("devfs", 5);
+    fsm_register(fs);
+    fs->mount = devfs_mount;
+    fs->unmount = devfs_unmount;
+}
+
+struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
+                                       .open = default_inode_open,
+                                       .mkdir = default_inode_mkdir,
+                                       .rmdir = default_inode_rmdir };
+
+struct v_file_ops devfs_file_ops = { .close = default_file_close,
+                                     .read = devfs_read,
+                                     .write = devfs_write,
+                                     .seek = default_file_seek,
+                                     .readdir = devfs_readdir };
\ No newline at end of file
diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c
new file mode 100644 (file)
index 0000000..aafdf0e
--- /dev/null
@@ -0,0 +1,127 @@
+#include <klibc/stdio.h>
+#include <lunaix/device.h>
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+static DEFINE_LLIST(root_list);
+
+static volatile dev_t devid = 0;
+
+struct device*
+__device_add(struct device* parent,
+             void* underlay,
+             char* name_fmt,
+             uint32_t type,
+             va_list args)
+{
+    struct device* dev = vzalloc(sizeof(struct device));
+
+    if (parent) {
+        assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
+    }
+
+    size_t strlen =
+      __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
+
+    dev->dev_id = devid++;
+    dev->name = HSTR(dev->name_val, strlen);
+    dev->parent = parent;
+    dev->underlay = underlay;
+    dev->dev_type = type;
+
+    hstr_rehash(&dev->name, HSTR_FULL_HASH);
+    llist_append(&root_list, &dev->siblings);
+
+    return dev;
+}
+
+struct device*
+device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      __device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      __device_add(parent, underlay, name_fmt, DEV_IFVOL, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev = __device_add(parent, NULL, name_fmt, DEV_IFCAT, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (pos->dev_id == id) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+struct device*
+device_getbyname(struct llist_header* devlist, struct hstr* name)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (HSTR_EQ(&pos->name, name)) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+void
+device_remove(struct device* dev)
+{
+    llist_delete(&dev->siblings);
+    vfree(dev);
+}
+
+struct device*
+device_getbyoffset(struct llist_header* devlist, int offset)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    int off = 0;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (off++ >= offset) {
+            return pos;
+        }
+    }
+    return NULL;
+}
\ No newline at end of file
index 74fdef7baa3e929702e9d444893a66b822b3ab1a..6de3f381d7aec49b10c80da02c03efd36c821c65 100644 (file)
@@ -1,4 +1,5 @@
 #include <lunaix/fs.h>
+#include <lunaix/fs/devfs.h>
 #include <lunaix/fs/ramfs.h>
 #include <lunaix/fs/twifs.h>
 
@@ -7,5 +8,7 @@ fsm_register_all()
 {
     ramfs_init();
     twifs_init();
-    // Add more fs implementation
+    devfs_init();
+
+    // ... more fs implementation
 }
\ No newline at end of file
index 7b83757e91b26740ac43426bbda421934a226750..486d6954152126b3ddad1e24fdd5a08c3bb00be7 100644 (file)
@@ -233,7 +233,7 @@ __DEFINE_LXSYSCALL4(int,
 
     // By our convention.
     // XXX could we do better?
-    struct device* device = (struct device*)dev->data;
+    struct device* device = (struct device*)dev->inode->data;
 
     if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) {
         errno = ENOTDEV;
index 83bd0bd26a3271e6d2719e591d8ee9caa48a36e0..7fbc2268008b61a4777b3420cb817f777e37fbec 100644 (file)
@@ -367,6 +367,7 @@ vfs_d_alloc(struct v_dnode* parent, struct hstr* name)
 
     if (parent) {
         dnode->super_block = parent->super_block;
+        dnode->mnt = parent->mnt;
     }
 
     lru_use_one(dnode_lru, &dnode->lru);
index 30e06ca731f1d8ee96d2c413c3a8894a852e0303..a443ec039a724cfb575bbcfcd63ddebfdc33d4ae 100644 (file)
@@ -72,19 +72,17 @@ _kernel_init()
     cake_init();
     valloc_init();
 
+    lxconsole_init();
+
     vfs_init();
     fsm_init();
 
-    device_init();
-
     if ((errno = vfs_mount_root("ramfs", NULL))) {
         panickf("Fail to mount root. (errno=%d)", errno);
     }
 
-    // FIXME replace with more specific fs for device.
-    vfs_mount("/dev", "twifs", NULL, MNT_RO);
-
-    lxconsole_init();
+    vfs_mount("/dev", "devfs", NULL, 0);
+    vfs_mount("/sys", "twifs", NULL, MNT_RO);
 
     sched_init();
 
index e137b8e28009dd89d477242a3fd99871c7fa5492..32e1effca8044b19395e4dac5777656dcdb1117b 100644 (file)
@@ -46,8 +46,8 @@ __do_reserved_memory(int unlock);
 
 #define USE_DEMO
 // #define DEMO_SIGNAL
-#define DEMO_READDIR
-//#define DEMO_IOTEST
+//#define DEMO_READDIR
+#define DEMO_IOTEST
 
 extern void
 _pconsole_main();
@@ -90,6 +90,7 @@ __proc0_usr()
 #else
         _lxinit_main();
 #endif
+        _exit(0);
     }
 
     waitpid(p, 0, 0);