]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
refactor: remove namespace callbacks from struct file_operations
authorTulio A M Mendes <[email protected]>
Sat, 14 Feb 2026 03:24:52 +0000 (00:24 -0300)
committerTulio A M Mendes <[email protected]>
Sat, 14 Feb 2026 03:24:52 +0000 (00:24 -0300)
Complete the file_operations / inode_operations separation:

- fs.h: struct file_operations now contains only per-fd I/O ops:
  read, write, open, close, ioctl, mmap, poll
- fs.h: struct inode_operations exclusively owns namespace/metadata:
  lookup, readdir, create, mkdir, unlink, rmdir, rename, truncate, link
- Migrated ext2 and initrd (missed in previous commits)
- Removed all f_ops fallback paths in fs.c, syscall.c, overlayfs.c,
  kconsole.c — everything now uses i_ops for namespace operations
- Clean separation: file_operations = fd I/O, inode_operations = namespace

All FSes migrated: diskfs, devfs, procfs, tmpfs, overlayfs, persistfs,
pty, fat, ext2, initrd.

cppcheck clean, 20/20 smoke tests pass.

include/fs.h
src/drivers/initrd.c
src/kernel/ext2.c
src/kernel/fs.c
src/kernel/kconsole.c
src/kernel/overlayfs.c
src/kernel/syscall.c

index 36ef75dc67948ac5c1113f067c56cf0b45abbbd9..7b07f0dd5eba5cdbd5881c53812c4c8596bb26ab 100644 (file)
 
 struct fs_node; /* forward declaration for file_operations */
 
-/* Shared file operations table — filesystems define one static instance
- * per node type (file, dir, device) and point every node's f_ops at it.
- * During the migration period, the VFS checks f_ops first, then falls
- * back to per-node function pointers (legacy). */
+/* File operations — per-open-fd I/O (requires an open file descriptor) */
 struct file_operations {
     uint32_t (*read)(struct fs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer);
     uint32_t (*write)(struct fs_node* node, uint32_t offset, uint32_t size, const uint8_t* buffer);
     void (*open)(struct fs_node* node);
     void (*close)(struct fs_node* node);
-    struct fs_node* (*finddir)(struct fs_node* node, const char* name);
-    int (*readdir)(struct fs_node* node, uint32_t* inout_index, void* buf, uint32_t buf_len);
     int (*ioctl)(struct fs_node* node, uint32_t cmd, void* arg);
     uintptr_t (*mmap)(struct fs_node* node, uintptr_t addr, uint32_t length, uint32_t prot, uint32_t offset);
     int (*poll)(struct fs_node* node, int events);
-    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);
 };
 
 /* Inode operations — namespace / metadata (no open fd required) */
index 00563e8e66633fd322f150152dd0dda71dbe11d2..89e32c73dbb79ffaf0826d3ad13920a4eac12965 100644 (file)
@@ -206,8 +206,10 @@ static const struct file_operations initrd_file_ops = {
     .read = initrd_read_impl,
 };
 
-static const struct file_operations initrd_dir_ops = {
-    .finddir = initrd_finddir,
+static const struct file_operations initrd_dir_ops = {0};
+
+static const struct inode_operations initrd_dir_iops = {
+    .lookup = initrd_finddir,
 };
 
 static void initrd_finalize_nodes(void) {
@@ -224,6 +226,7 @@ static void initrd_finalize_nodes(void) {
             n->f_ops = &initrd_file_ops;
         } else if (e->flags & FS_DIRECTORY) {
             n->f_ops = &initrd_dir_ops;
+            n->i_ops = &initrd_dir_iops;
         }
     }
 }
index 41f122a9ed4d4582a8553546e72e911fde7acb80..fd9214baa8778243d5d0856ee81ffed7204428f3 100644 (file)
@@ -545,12 +545,18 @@ static const struct file_operations ext2_file_fops = {
     .read     = ext2_file_read,
     .write    = ext2_file_write,
     .close    = ext2_close_impl,
+};
+
+static const struct inode_operations ext2_file_iops = {
     .truncate = ext2_truncate_impl,
 };
 
 static const struct file_operations ext2_dir_fops = {
     .close   = ext2_close_impl,
-    .finddir = ext2_finddir,
+};
+
+static const struct inode_operations ext2_dir_iops = {
+    .lookup  = ext2_finddir,
     .readdir = ext2_readdir_impl,
     .create  = ext2_create_impl,
     .mkdir   = ext2_mkdir_impl,
@@ -586,6 +592,7 @@ static struct ext2_node* ext2_make_node(uint32_t ino, const struct ext2_inode* i
         en->vfs.flags = FS_DIRECTORY;
         en->vfs.length = inode->i_size;
         en->vfs.f_ops = &ext2_dir_fops;
+        en->vfs.i_ops = &ext2_dir_iops;
     } else if ((inode->i_mode & 0xF000) == EXT2_S_IFLNK) {
         en->vfs.flags = FS_SYMLINK;
         en->vfs.length = inode->i_size;
@@ -598,6 +605,7 @@ static struct ext2_node* ext2_make_node(uint32_t ino, const struct ext2_inode* i
         en->vfs.flags = FS_FILE;
         en->vfs.length = inode->i_size;
         en->vfs.f_ops = &ext2_file_fops;
+        en->vfs.i_ops = &ext2_file_iops;
     }
 
     return en;
@@ -1420,6 +1428,7 @@ fs_node_t* ext2_mount(int drive, uint32_t partition_lba) {
     g_ext2_root.vfs.mode = root_inode.i_mode;
     g_ext2_root.ino = EXT2_ROOT_INO;
     g_ext2_root.vfs.f_ops = &ext2_dir_fops;
+    g_ext2_root.vfs.i_ops = &ext2_dir_iops;
 
     g_ext2_ready = 1;
 
index e4009e068db30568d8472a59c6c079181fadaa54..b4967436f88df52c0b64153b608755643379815d 100644 (file)
@@ -153,7 +153,6 @@ 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->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;
@@ -207,8 +206,6 @@ int vfs_create(const char* path, uint32_t flags, fs_node_t** out) {
     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;
 }
 
@@ -220,8 +217,6 @@ int vfs_mkdir(const char* path) {
     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;
 }
 
@@ -233,8 +228,6 @@ int vfs_unlink(const char* path) {
     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;
 }
 
@@ -246,8 +239,6 @@ int vfs_rmdir(const char* path) {
     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;
 }
 
@@ -259,8 +250,6 @@ int vfs_rename(const char* old_path, const char* new_path) {
     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;
 }
 
@@ -271,8 +260,6 @@ int vfs_truncate(const char* path, uint32_t length) {
     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;
 }
 
@@ -288,7 +275,5 @@ int vfs_link(const char* old_path, const char* new_path) {
     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 eb8349a839f14afd4724f6a75707f63892352519..2046e6e5c3f3a50ec1a4064c51e00178cf943e1e 100644 (file)
@@ -277,7 +277,7 @@ static void kconsole_ls(const char* path) {
     }
 
     int (*fn_readdir)(struct fs_node*, uint32_t*, void*, uint32_t) = NULL;
-    if (dir->f_ops && dir->f_ops->readdir) fn_readdir = dir->f_ops->readdir;
+    if (dir->i_ops && dir->i_ops->readdir) fn_readdir = dir->i_ops->readdir;
     if (!fn_readdir) {
         kprintf("ls: not a directory\n");
         return;
index f1abef41c61779027b0317bfcb7e755ad487a23a..a22a75386fbcf12c96afe230943dfc47a16adbf8 100644 (file)
@@ -179,8 +179,6 @@ static int overlay_readdir_impl(struct fs_node* node, uint32_t* inout_index, voi
     if (!src) return 0;
     if (src->i_ops && src->i_ops->readdir)
         return src->i_ops->readdir(src, inout_index, buf, buf_len);
-    if (src->f_ops && src->f_ops->readdir)
-        return src->f_ops->readdir(src, inout_index, buf, buf_len);
     return 0;
 }
 
@@ -193,18 +191,10 @@ static struct fs_node* overlay_finddir_impl(struct fs_node* node, const char* na
     fs_node_t* upper_child = NULL;
     fs_node_t* lower_child = NULL;
 
-    if (dir->upper) {
-        if (dir->upper->i_ops && dir->upper->i_ops->lookup)
-            upper_child = dir->upper->i_ops->lookup(dir->upper, name);
-        else if (dir->upper->f_ops && dir->upper->f_ops->finddir)
-            upper_child = dir->upper->f_ops->finddir(dir->upper, name);
-    }
-    if (dir->lower) {
-        if (dir->lower->i_ops && dir->lower->i_ops->lookup)
-            lower_child = dir->lower->i_ops->lookup(dir->lower, name);
-        else if (dir->lower->f_ops && dir->lower->f_ops->finddir)
-            lower_child = dir->lower->f_ops->finddir(dir->lower, name);
-    }
+    if (dir->upper && dir->upper->i_ops && dir->upper->i_ops->lookup)
+        upper_child = dir->upper->i_ops->lookup(dir->upper, name);
+    if (dir->lower && dir->lower->i_ops && dir->lower->i_ops->lookup)
+        lower_child = dir->lower->i_ops->lookup(dir->lower, name);
 
     if (!upper_child && !lower_child) return 0;
     return overlay_wrap_child(dir, name, lower_child, upper_child);
index 0d19e24f4d89c6659c32ab1ac52832b8d2c43e3b..5f9e865cbd3fa9f041474dc36e54e15fb124ed38 100644 (file)
@@ -1161,8 +1161,8 @@ static int syscall_open_impl(const char* user_path, uint32_t flags) {
         return -ENOENT;
     } else if ((flags & 0x200U) != 0U && node->flags == FS_FILE) {
         /* O_TRUNC on existing file */
-        if (node->f_ops && node->f_ops->truncate) {
-            node->f_ops->truncate(node, 0);
+        if (node->i_ops && node->i_ops->truncate) {
+            node->i_ops->truncate(node, 0);
             node->length = 0;
         }
     }
@@ -1444,7 +1444,6 @@ static int syscall_getdents_impl(int fd, void* user_buf, uint32_t len) {
     if (f->node->flags != FS_DIRECTORY) return -ENOTDIR;
     int (*fn_readdir)(struct fs_node*, uint32_t*, void*, uint32_t) = NULL;
     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];
@@ -1985,7 +1984,7 @@ static int syscall_readlink_impl(const char* user_path, char* user_buf, uint32_t
     fs_node_t* dir = vfs_lookup(parent);
     if (!dir) return -ENOENT;
     fs_node_t* (*fn_finddir)(fs_node_t*, const char*) = NULL;
-    if (dir->f_ops && dir->f_ops->finddir) fn_finddir = dir->f_ops->finddir;
+    if (dir->i_ops && dir->i_ops->lookup) fn_finddir = dir->i_ops->lookup;
     if (!fn_finddir) return -ENOENT;
 
     fs_node_t* node = fn_finddir(dir, leaf);