From: Tulio A M Mendes Date: Sat, 14 Feb 2026 01:19:42 +0000 (-0300) Subject: refactor: add struct inode_operations + VFS dispatch with fallback X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=a2bac64af69e6830dfcb18cbb7642cf7ab3fbefc;p=AdrOS.git refactor: add struct inode_operations + VFS dispatch with fallback 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. --- diff --git a/include/fs.h b/include/fs.h index a3ecf4b..bc41612 100644 --- a/include/fs.h +++ b/include/fs.h @@ -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 { diff --git a/src/kernel/fs.c b/src/kernel/fs.c index c42cd24..76ea242 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -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; diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 465fb56..43b5edd 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -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];