]> 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 a185040c1d9c60651511b31ac8b699ddf4d75eee..36ef75dc67948ac5c1113f067c56cf0b45abbbd9 100644 (file)
@@ -52,6 +52,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;
@@ -63,6 +77,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 e4156d758bbf2ca0358a62964d82a11a18dbd64b..e4009e068db30568d8472a59c6c079181fadaa54 100644 (file)
@@ -152,7 +152,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;
@@ -204,6 +205,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;
@@ -215,6 +218,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;
@@ -226,6 +231,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;
@@ -237,6 +244,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;
@@ -248,6 +257,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;
@@ -258,6 +269,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;
@@ -273,6 +286,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 66ed72b249ce8edb77b4338f88097577fb4fba6d..0d19e24f4d89c6659c32ab1ac52832b8d2c43e3b 100644 (file)
@@ -1443,7 +1443,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];