From 6c60d13bbf884d648406a573e611763fea682119 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Sat, 14 Feb 2026 00:24:52 -0300 Subject: [PATCH] refactor: remove namespace callbacks from struct file_operations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 | 15 +-------------- src/drivers/initrd.c | 7 +++++-- src/kernel/ext2.c | 11 ++++++++++- src/kernel/fs.c | 15 --------------- src/kernel/kconsole.c | 2 +- src/kernel/overlayfs.c | 18 ++++-------------- src/kernel/syscall.c | 7 +++---- 7 files changed, 24 insertions(+), 51 deletions(-) diff --git a/include/fs.h b/include/fs.h index bc41612..69411bb 100644 --- a/include/fs.h +++ b/include/fs.h @@ -19,28 +19,15 @@ 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) */ diff --git a/src/drivers/initrd.c b/src/drivers/initrd.c index b3a7fd7..f12ec54 100644 --- a/src/drivers/initrd.c +++ b/src/drivers/initrd.c @@ -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; } } } diff --git a/src/kernel/ext2.c b/src/kernel/ext2.c index abb406e..e501cb7 100644 --- a/src/kernel/ext2.c +++ b/src/kernel/ext2.c @@ -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; diff --git a/src/kernel/fs.c b/src/kernel/fs.c index 76ea242..f04fc2d 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -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; } diff --git a/src/kernel/kconsole.c b/src/kernel/kconsole.c index 5104389..0b157d1 100644 --- a/src/kernel/kconsole.c +++ b/src/kernel/kconsole.c @@ -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; diff --git a/src/kernel/overlayfs.c b/src/kernel/overlayfs.c index baee9f5..c769fbf 100644 --- a/src/kernel/overlayfs.c +++ b/src/kernel/overlayfs.c @@ -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); diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 43b5edd..25ad284 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -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); -- 2.43.0