]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
refactor: add struct inode_operations + VFS dispatch with fallback
authorTulio A M Mendes <[email protected]>
Sat, 14 Feb 2026 01:19:42 +0000 (22:19 -0300)
committerTulio A M Mendes <[email protected]>
Sat, 14 Feb 2026 01:19:42 +0000 (22:19 -0300)
Infrastructure for separating file_operations (per-fd I/O) from
inode_operations (namespace/metadata):

- fs.h: added struct inode_operations with lookup, readdir, create,
  mkdir, unlink, rmdir, rename, truncate, link callbacks
- fs.h: added i_ops pointer to fs_node_t alongside existing f_ops
- fs.c: VFS dispatch checks i_ops first, falls back to f_ops for
  all namespace operations (lookup, create, mkdir, unlink, rmdir,
  rename, truncate, link)
- syscall.c: getdents dispatch checks i_ops->readdir first

This is backward-compatible: all existing filesystems continue to
work through the f_ops fallback path. Each FS will be migrated
individually in subsequent commits.

20/20 smoke tests pass.

include/fs.h
src/kernel/fs.c
src/kernel/syscall.c

index a3ecf4b891e40aa8456a09a1915343e779ed95ba..bc41612830804b46f300b5b84b607b407ee022c9 100644 (file)
@@ -43,6 +43,20 @@ struct file_operations {
     int (*link)(struct fs_node* dir, const char* name, struct fs_node* target);
 };
 
+/* Inode operations — namespace / metadata (no open fd required) */
+struct inode_operations {
+    struct fs_node* (*lookup)(struct fs_node* dir, const char* name);
+    int (*readdir)(struct fs_node* dir, uint32_t* inout_index, void* buf, uint32_t buf_len);
+    int (*create)(struct fs_node* dir, const char* name, uint32_t flags, struct fs_node** out);
+    int (*mkdir)(struct fs_node* dir, const char* name);
+    int (*unlink)(struct fs_node* dir, const char* name);
+    int (*rmdir)(struct fs_node* dir, const char* name);
+    int (*rename)(struct fs_node* old_dir, const char* old_name,
+                  struct fs_node* new_dir, const char* new_name);
+    int (*truncate)(struct fs_node* node, uint32_t length);
+    int (*link)(struct fs_node* dir, const char* name, struct fs_node* target);
+};
+
 typedef struct fs_node {
     char name[128];
     uint32_t flags;
@@ -54,6 +68,7 @@ typedef struct fs_node {
     char symlink_target[128];
 
     const struct file_operations* f_ops;
+    const struct inode_operations* i_ops;
 } fs_node_t;
 
 struct vfs_dirent {
index c42cd24b98cc68ade20be1d7375b6b55c377269a..76ea2420930b7f976daaba00f80ccd51e9e5ca73 100644 (file)
@@ -143,7 +143,8 @@ static fs_node_t* vfs_lookup_depth(const char* path, int depth) {
 
         if (!cur) return NULL;
         fs_node_t* (*fn_finddir)(fs_node_t*, const char*) = NULL;
-        if (cur->f_ops && cur->f_ops->finddir) fn_finddir = cur->f_ops->finddir;
+        if (cur->i_ops && cur->i_ops->lookup) fn_finddir = cur->i_ops->lookup;
+        else if (cur->f_ops && cur->f_ops->finddir) fn_finddir = cur->f_ops->finddir;
         if (!fn_finddir) return NULL;
         cur = fn_finddir(cur, part);
         if (!cur) return NULL;
@@ -195,6 +196,8 @@ int vfs_create(const char* path, uint32_t flags, fs_node_t** out) {
     fs_node_t* parent = vfs_lookup_parent(path, name, sizeof(name));
     if (!parent) return -ENOENT;
     if (parent->flags != FS_DIRECTORY) return -ENOTDIR;
+    if (parent->i_ops && parent->i_ops->create)
+        return parent->i_ops->create(parent, name, flags, out);
     if (parent->f_ops && parent->f_ops->create)
         return parent->f_ops->create(parent, name, flags, out);
     return -ENOSYS;
@@ -206,6 +209,8 @@ int vfs_mkdir(const char* path) {
     fs_node_t* parent = vfs_lookup_parent(path, name, sizeof(name));
     if (!parent) return -ENOENT;
     if (parent->flags != FS_DIRECTORY) return -ENOTDIR;
+    if (parent->i_ops && parent->i_ops->mkdir)
+        return parent->i_ops->mkdir(parent, name);
     if (parent->f_ops && parent->f_ops->mkdir)
         return parent->f_ops->mkdir(parent, name);
     return -ENOSYS;
@@ -217,6 +222,8 @@ int vfs_unlink(const char* path) {
     fs_node_t* parent = vfs_lookup_parent(path, name, sizeof(name));
     if (!parent) return -ENOENT;
     if (parent->flags != FS_DIRECTORY) return -ENOTDIR;
+    if (parent->i_ops && parent->i_ops->unlink)
+        return parent->i_ops->unlink(parent, name);
     if (parent->f_ops && parent->f_ops->unlink)
         return parent->f_ops->unlink(parent, name);
     return -ENOSYS;
@@ -228,6 +235,8 @@ int vfs_rmdir(const char* path) {
     fs_node_t* parent = vfs_lookup_parent(path, name, sizeof(name));
     if (!parent) return -ENOENT;
     if (parent->flags != FS_DIRECTORY) return -ENOTDIR;
+    if (parent->i_ops && parent->i_ops->rmdir)
+        return parent->i_ops->rmdir(parent, name);
     if (parent->f_ops && parent->f_ops->rmdir)
         return parent->f_ops->rmdir(parent, name);
     return -ENOSYS;
@@ -239,6 +248,8 @@ int vfs_rename(const char* old_path, const char* new_path) {
     fs_node_t* old_parent = vfs_lookup_parent(old_path, old_name, sizeof(old_name));
     fs_node_t* new_parent = vfs_lookup_parent(new_path, new_name, sizeof(new_name));
     if (!old_parent || !new_parent) return -ENOENT;
+    if (old_parent->i_ops && old_parent->i_ops->rename)
+        return old_parent->i_ops->rename(old_parent, old_name, new_parent, new_name);
     if (old_parent->f_ops && old_parent->f_ops->rename)
         return old_parent->f_ops->rename(old_parent, old_name, new_parent, new_name);
     return -ENOSYS;
@@ -249,6 +260,8 @@ int vfs_truncate(const char* path, uint32_t length) {
     fs_node_t* node = vfs_lookup(path);
     if (!node) return -ENOENT;
     if (node->flags != FS_FILE) return -EISDIR;
+    if (node->i_ops && node->i_ops->truncate)
+        return node->i_ops->truncate(node, length);
     if (node->f_ops && node->f_ops->truncate)
         return node->f_ops->truncate(node, length);
     return -ENOSYS;
@@ -264,6 +277,8 @@ int vfs_link(const char* old_path, const char* new_path) {
     fs_node_t* parent = vfs_lookup_parent(new_path, name, sizeof(name));
     if (!parent) return -ENOENT;
     if (parent->flags != FS_DIRECTORY) return -ENOTDIR;
+    if (parent->i_ops && parent->i_ops->link)
+        return parent->i_ops->link(parent, name, target);
     if (parent->f_ops && parent->f_ops->link)
         return parent->f_ops->link(parent, name, target);
     return -ENOSYS;
index 465fb569cf482e0d9932b70d72034ecd180a6fbc..43b5edd74c7099e5c11b4e1a311c07cc9bc477f0 100644 (file)
@@ -1434,7 +1434,8 @@ static int syscall_getdents_impl(int fd, void* user_buf, uint32_t len) {
     if (!f || !f->node) return -EBADF;
     if (f->node->flags != FS_DIRECTORY) return -ENOTDIR;
     int (*fn_readdir)(struct fs_node*, uint32_t*, void*, uint32_t) = NULL;
-    if (f->node->f_ops && f->node->f_ops->readdir) fn_readdir = f->node->f_ops->readdir;
+    if (f->node->i_ops && f->node->i_ops->readdir) fn_readdir = f->node->i_ops->readdir;
+    else if (f->node->f_ops && f->node->f_ops->readdir) fn_readdir = f->node->f_ops->readdir;
     if (!fn_readdir) return -ENOSYS;
 
     uint8_t kbuf[256];