]> 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 bc41612830804b46f300b5b84b607b407ee022c9..69411bb2a38048f87441bbdf7bddb83cfd08e97a 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 b3a7fd7bac3cb45ff69be49fc5053597e97a9e45..f12ec544086111a9c56988f51ab8e6c122e9b3f5 100644 (file)
@@ -197,8 +197,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) {
@@ -215,6 +217,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 abb406e13e84411c87af53f5b7a460440a69fa78..e501cb736325bdb6ced00ab934a9474faef6e11a 100644 (file)
@@ -536,12 +536,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,
@@ -577,6 +583,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;
@@ -589,6 +596,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;
@@ -1411,6 +1419,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 76ea2420930b7f976daaba00f80ccd51e9e5ca73..f04fc2d82fa6d0b7c211ffd51ab7a474e89b9718 100644 (file)
@@ -144,7 +144,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;
@@ -198,8 +197,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;
 }
 
@@ -211,8 +208,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;
 }
 
@@ -224,8 +219,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;
 }
 
@@ -237,8 +230,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;
 }
 
@@ -250,8 +241,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;
 }
 
@@ -262,8 +251,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;
 }
 
@@ -279,7 +266,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 51043891b0f3bbf8b746525bd0d663ad60b54708..0b157d1a915351c16b872b8100d8495b73981f58 100644 (file)
@@ -268,7 +268,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 baee9f5c0761d9c9f41ed63bd23611432e7f4451..c769fbf5b44152bee8b6e8304cf76dbee20e31d0 100644 (file)
@@ -170,8 +170,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;
 }
 
@@ -184,18 +182,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 43b5edd74c7099e5c11b4e1a311c07cc9bc477f0..25ad2843a8cb471582891ac6a655d1f9f5dae54f 100644 (file)
@@ -1152,8 +1152,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;
         }
     }
@@ -1435,7 +1435,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];
@@ -1976,7 +1975,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);