From 8cace3f05003c6cb4d38c36890055f03151c2ad4 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Fri, 16 Oct 2026 02:39:56 +0800 Subject: Remove old code Signed-off-by: Richard Qin --- fs/Build.mk | 8 -- fs/chardev.cc | 43 -------- fs/dcache.cc | 287 ------------------------------------------------------ fs/devfs.cc | 137 -------------------------- fs/fd.cc | 216 ---------------------------------------- fs/file_table.cc | 164 ------------------------------- fs/fs_struct.cc | 90 ----------------- fs/initramfs.cc | 285 ----------------------------------------------------- fs/inode.cc | 166 ------------------------------- fs/namei.cc | 250 ----------------------------------------------- fs/pipe.cc | 278 ---------------------------------------------------- fs/ramfs/file.cc | 216 ---------------------------------------- fs/ramfs/inode.cc | 164 ------------------------------- fs/ramfs/super.cc | 154 ----------------------------- fs/super.cc | 95 ------------------ fs/vfs_init.cc | 78 --------------- 16 files changed, 2631 deletions(-) delete mode 100644 fs/Build.mk delete mode 100644 fs/chardev.cc delete mode 100644 fs/dcache.cc delete mode 100644 fs/devfs.cc delete mode 100644 fs/fd.cc delete mode 100644 fs/file_table.cc delete mode 100644 fs/fs_struct.cc delete mode 100644 fs/initramfs.cc delete mode 100644 fs/inode.cc delete mode 100644 fs/namei.cc delete mode 100644 fs/pipe.cc delete mode 100644 fs/ramfs/file.cc delete mode 100644 fs/ramfs/inode.cc delete mode 100644 fs/ramfs/super.cc delete mode 100644 fs/super.cc delete mode 100644 fs/vfs_init.cc (limited to 'fs') diff --git a/fs/Build.mk b/fs/Build.mk deleted file mode 100644 index 057d1df..0000000 --- a/fs/Build.mk +++ /dev/null @@ -1,8 +0,0 @@ -targets += fs/core -target.fs/core.kind := source-set -target.fs/core.sources := \ - fs/super.cc fs/inode.cc fs/dcache.cc fs/file_table.cc fs/fd.cc \ - fs/fs_struct.cc fs/namei.cc fs/ramfs/inode.cc fs/ramfs/file.cc \ - fs/ramfs/super.cc fs/vfs_init.cc fs/chardev.cc fs/devfs.cc fs/pipe.cc \ - fs/initramfs.cc - diff --git a/fs/chardev.cc b/fs/chardev.cc deleted file mode 100644 index fa96276..0000000 --- a/fs/chardev.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * chardev.cc — Character device registry - * - * Simple linked list of registered cdevs, searched by dev number. - */ - -#include -#include -#include -#include - -static list_node g_cdev_list; -static Spinlock g_cdev_lock; - -void cdev_init() -{ - list_init(&g_cdev_list); -} - -void cdev_register(cdev* dev) -{ - LockGuard guard(g_cdev_lock); - list_init(&dev->list); - list_add_tail(&dev->list, &g_cdev_list); - printk("[cdev] registered '%s' (%d,%d)\n", - dev->name, MAJOR(dev->dev), MINOR(dev->dev)); -} - -cdev* cdev_find(uint32 dev_nr) -{ - LockGuard guard(g_cdev_lock); - list_node* pos; - for (pos = g_cdev_list.prev; pos != &g_cdev_list; pos = pos->prev) { - cdev* cd = container_of(pos, cdev, list); - if (cd->dev == dev_nr) { - return cd; - } - } - return nullptr; -} diff --git a/fs/dcache.cc b/fs/dcache.cc deleted file mode 100644 index 94ab287..0000000 --- a/fs/dcache.cc +++ /dev/null @@ -1,287 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * dcache.cc — Directory entry cache - * - * Provides dentry allocation, lookup, instantiation, and d_path. - */ - -#include -#include -#include -#include -#include -#include - -/* ================================================================== */ -/* Hash function */ -/* ================================================================== */ - -uint32 full_name_hash(const char* name, uint32 len) -{ - uint32 hash = 0; - for (uint32 i = 0; i < len; i++) - hash = hash * 31 + static_cast(name[i]); - return hash; -} - -/* ================================================================== */ -/* d_set_type — set DCACHE_*_TYPE bits from inode mode */ -/* ================================================================== */ - -void d_set_type(dentry* de, uint32 i_mode) -{ - de->d_flags &= ~DCACHE_ENTRY_TYPE; - - if (S_ISDIR(i_mode)) - de->d_flags |= DCACHE_DIRECTORY_TYPE; - else if (S_ISLNK(i_mode)) - de->d_flags |= DCACHE_SYMLINK_TYPE; - else if (S_ISREG(i_mode)) - de->d_flags |= DCACHE_REGULAR_TYPE; - else - de->d_flags |= DCACHE_SPECIAL_TYPE; -} - -/* ================================================================== */ -/* d_alloc — allocate a dentry under a parent */ -/* ================================================================== */ - -static void dentry_init(dentry* de, dentry* parent, const qstr* name) -{ - de->d_flags = DCACHE_MISS_TYPE; /* negative until instantiated */ - de->d_parent = parent ? parent : de; - de->d_inode = nullptr; - de->d_op = nullptr; - de->d_sb = parent ? parent->d_sb : nullptr; - de->d_time = 0; - de->d_fsdata = nullptr; - de->d_lockref.store(1); - - list_init(&de->d_lru); - list_init(&de->d_child); - list_init(&de->d_children); - list_init(&de->d_alias); - - /* Copy name */ - if (name && name->name && name->len > 0) { - uint32 len = name->len; - if (len < DNAME_INLINE_LEN) { - for (uint32 i = 0; i < len; i++) - de->d_iname[i] = name->name[i]; - de->d_iname[len] = '\0'; - de->d_name.name = reinterpret_cast(de->d_iname); - } else { - /* Heap-allocate for long names */ - char* buf = new char[len + 1]; - for (uint32 i = 0; i < len; i++) - buf[i] = name->name[i]; - buf[len] = '\0'; - de->d_name.name = buf; - } - de->d_name.len = len; - de->d_name.hash = name->hash ? name->hash : full_name_hash(name->name, len); - } else { - de->d_iname[0] = '\0'; - de->d_name.name = reinterpret_cast(de->d_iname); - de->d_name.len = 0; - de->d_name.hash = 0; - } -} - -dentry* d_alloc(dentry* parent, const qstr* name) -{ - auto* de = new dentry{}; - if (!de) return nullptr; - - dentry_init(de, parent, name); - de->d_sb = parent->d_sb; - - /* Use sb default d_op if set */ - if (parent->d_sb->s_d_op) - de->d_op = parent->d_sb->s_d_op; - - /* Link into parent's children list */ - if (parent) { - LockGuard guard(parent->d_lock); - list_add_tail(&de->d_child, &parent->d_children); - dget(parent); /* child holds ref on parent */ - } - - return de; -} - -dentry* d_alloc_anon(super_block* sb) -{ - auto* de = new dentry{}; - if (!de) return nullptr; - - dentry_init(de, nullptr, nullptr); - de->d_sb = sb; - de->d_parent = de; /* root: parent is self */ - - return de; -} - -/* ================================================================== */ -/* d_instantiate — bind an inode to a dentry */ -/* ================================================================== */ - -void d_instantiate(dentry* de, inode* ip) -{ - if (!ip) return; - - LockGuard guard(de->d_lock); - de->d_inode = ip; - d_set_type(de, ip->i_mode); - - /* Add to inode's alias list */ - list_add_tail(&de->d_alias, &ip->i_dentry); -} - -/* ================================================================== */ -/* d_make_root — create root dentry for a superblock */ -/* ================================================================== */ - -dentry* d_make_root(inode* root_inode) -{ - if (!root_inode) return nullptr; - - dentry* de = d_alloc_anon(root_inode->i_sb); - if (!de) { - iput(root_inode); - return nullptr; - } - - d_instantiate(de, root_inode); - return de; -} - -/* ================================================================== */ -/* d_add — combined d_instantiate + d_rehash */ -/* ================================================================== */ - -void d_add(dentry* de, inode* ip) -{ - d_instantiate(de, ip); - /* d_rehash would add to dcache hash table; simplified for now */ -} - -/* ================================================================== */ -/* d_lookup — search children of parent for a name match */ -/* ================================================================== */ - -dentry* d_lookup(const dentry* parent, const qstr* name) -{ - LockGuard guard(const_cast(parent->d_lock)); - - list_node* pos; - list_for_each(pos, &parent->d_children) { - dentry* child = list_entry(pos, dentry, d_child); - - if (child->d_name.len != name->len) - continue; - - /* Compare names */ - const char* a = child->d_name.name; - const char* b = name->name; - uint32 len = name->len; - bool match = true; - for (uint32 i = 0; i < len; i++) { - if (a[i] != b[i]) { match = false; break; } - } - if (match) { - dget(child); - return child; - } - } - - return nullptr; -} - -/* ================================================================== */ -/* dget / dput — dentry reference counting */ -/* ================================================================== */ - -dentry* dget(dentry* de) -{ - if (de) - de->d_lockref.fetch_add(1); - return de; -} - -void dput(dentry* de) -{ - if (!de) return; - - int old = de->d_lockref.fetch_sub(1); - if (old > 1) return; - - /* Last reference — could free, but for ramfs we keep dentries alive. - * A real implementation would check d_op->d_delete and possibly - * add to LRU for later reclaim. For now, just leak (Phase 1). */ -} - -/* ================================================================== */ -/* d_drop / d_delete */ -/* ================================================================== */ - -void d_drop(dentry* de) -{ - /* Remove from parent's children list */ - LockGuard guard(de->d_lock); - if (!list_empty(&de->d_child)) - list_del_init(&de->d_child); -} - -void d_delete(dentry* de) -{ - d_drop(de); -} - -/* ================================================================== */ -/* d_path — build absolute pathname from a path */ -/* ================================================================== */ - -char* d_path(const path* p, char* buf, int buflen) -{ - if (!p || !p->de || buflen <= 0) - return nullptr; - - /* Build path by walking up d_parent chain, writing backwards */ - char* end = buf + buflen - 1; - *end = '\0'; - - dentry* de = p->de; - - if (d_is_root(de)) { - if (end <= buf) return nullptr; - *(--end) = '/'; - return end; - } - - while (!d_is_root(de)) { - uint32 len = de->d_name.len; - end -= len; - if (end <= buf) return nullptr; - - const char* name = de->d_name.name; - for (uint32 i = 0; i < len; i++) - end[i] = name[i]; - - *(--end) = '/'; - de = de->d_parent; - } - - return end; -} - -/* ================================================================== */ -/* dcache_init */ -/* ================================================================== */ - -void dcache_init() -{ - /* Future: init dcache hash table */ -} diff --git a/fs/devfs.cc b/fs/devfs.cc deleted file mode 100644 index b4b2cf3..0000000 --- a/fs/devfs.cc +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * devfs.cc — /dev population and chardev-aware open - * - * Creates /dev as a subdirectory under the ramfs root, then - * populates device nodes. On open(), if the inode is S_IFCHR, - * we look up the cdev by i_rdev and use its fops. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* ================================================================== */ -/* devfs_create_node — create a char device inode under parent */ -/* ================================================================== */ - -static int devfs_create_node(dentry* parent, const char* name, - uint32 major, uint32 minor) -{ - inode* dir_ip = parent->d_inode; - if (!dir_ip || !dir_ip->i_op || !dir_ip->i_op->mknod) { - return -EPERM; - } - - qstr q{}; - q.name = name; - q.len = 0; - for (const char* s = name; *s; s++) { - q.len++; - } - - dentry* de = d_alloc(parent, &q); - if (!de) { - return -ENOMEM; - } - - int err = dir_ip->i_op->mknod(dir_ip, de, S_IFCHR | 0666, - MKDEV(major, minor)); - if (err) { - return err; - } - - return 0; -} - -/* ================================================================== */ -/* devfs_open — chardev-aware open hook */ -/* ================================================================== */ - -/* - * Called from sys_openat when the inode is S_IFCHR. - * Replaces f_op with the chardev's file_operations. - */ -int devfs_chrdev_open(inode* ip, file* fp) -{ - if (!S_ISCHR(ip->i_mode)) { - return 0; - } - - cdev* cd = cdev_find(ip->i_rdev); - if (!cd || !cd->fops) { - return -ENXIO; /* No such device */ - } - - fp->f_op = cd->fops; - - /* Call the device's own open if it has one */ - if (fp->f_op->open) { - return fp->f_op->open(ip, fp); - } - - return 0; -} - -/* ================================================================== */ -/* devfs_init — create /dev and populate device nodes */ -/* ================================================================== */ - -void devfs_init() -{ - if (!g_root_dentry || !g_root_dentry->d_inode) { - printk(KERN_ERR "[devfs] no root filesystem!\n"); - return; - } - - /* Create /dev directory — or reuse if initramfs already created it. - * Linux: devtmpfs similarly handles pre-existing directories. */ - inode* root_ip = g_root_dentry->d_inode; - - qstr dev_name{}; - dev_name.name = "dev"; - dev_name.len = 3; - dev_name.hash = full_name_hash("dev", 3); - - dentry* dev_de = d_lookup(g_root_dentry, &dev_name); - if (dev_de) { - /* /dev already exists (from initramfs) — reuse it */ - printk("[devfs] reusing existing /dev directory\n"); - } else { - /* Create /dev from scratch */ - if (!root_ip->i_op || !root_ip->i_op->mkdir) { - printk(KERN_ERR "[devfs] root has no mkdir!\n"); - return; - } - - dev_de = d_alloc(g_root_dentry, &dev_name); - if (!dev_de) { - printk(KERN_ERR "[devfs] failed to alloc /dev dentry\n"); - return; - } - - int err = root_ip->i_op->mkdir(root_ip, dev_de, S_IFDIR | 0755); - if (err) { - printk(KERN_ERR "[devfs] mkdir /dev failed: %d\n", err); - return; - } - } - - /* Populate: /dev/console (5,1) */ - devfs_create_node(dev_de, "console", 5, 1); - - /* Populate: /dev/null (1,3) */ - devfs_create_node(dev_de, "null", 1, 3); - - /* Populate: /dev/zero (1,5) */ - devfs_create_node(dev_de, "zero", 1, 5); - - printk("[devfs] /dev populated (console, null, zero)\n"); -} diff --git a/fs/fd.cc b/fs/fd.cc deleted file mode 100644 index 5fc8ab0..0000000 --- a/fs/fd.cc +++ /dev/null @@ -1,216 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * fd.cc — File descriptor table management - */ - -#include -#include -#include -#include - -/* ================================================================== */ -/* Bitmap helpers */ -/* ================================================================== */ - -static inline bool bit_test(const uint64* bmap, int bit) { - return (bmap[bit / 64] >> (bit % 64)) & 1; -} -static inline void bit_set(uint64* bmap, int bit) { - bmap[bit / 64] |= (1ULL << (bit % 64)); -} -static inline void bit_clear(uint64* bmap, int bit) { - bmap[bit / 64] &= ~(1ULL << (bit % 64)); -} - -/* ================================================================== */ -/* alloc_files_struct */ -/* ================================================================== */ - -files_struct* alloc_files_struct() -{ - auto* files = new files_struct{}; - if (!files) return nullptr; - - files->count.store(1); - files->next_fd = 0; - files->max_fds = NR_OPEN_DEFAULT; - - for (int i = 0; i < NR_OPEN_DEFAULT; i++) - files->fd_array[i] = nullptr; - - int bmap_words = (NR_OPEN_DEFAULT + 63) / 64; - for (int i = 0; i < bmap_words; i++) { - files->close_on_exec_init[i] = 0; - files->open_fds_init[i] = 0; - } - - return files; -} - -/* ================================================================== */ -/* put_files_struct — drop reference, free on last */ -/* ================================================================== */ - -void put_files_struct(files_struct* files) -{ - if (!files) return; - - int old = files->count.fetch_sub(1); - if (old > 1) return; - - /* Close all open fds */ - for (int i = 0; i < files->max_fds; i++) { - if (files->fd_array[i]) { - fput(files->fd_array[i]); - files->fd_array[i] = nullptr; - } - } - - delete files; -} - -/* ================================================================== */ -/* dup_fd — duplicate entire fd table (for fork) */ -/* ================================================================== */ - -files_struct* dup_fd(files_struct* old_files) -{ - auto* new_files = alloc_files_struct(); - if (!new_files) return nullptr; - - LockGuard guard(old_files->file_lock); - - for (int i = 0; i < old_files->max_fds; i++) { - file* fp = old_files->fd_array[i]; - if (fp) { - get_file(fp); - new_files->fd_array[i] = fp; - } - } - - /* Copy bitmaps */ - int bmap_words = (NR_OPEN_DEFAULT + 63) / 64; - for (int i = 0; i < bmap_words; i++) { - new_files->open_fds_init[i] = old_files->open_fds_init[i]; - new_files->close_on_exec_init[i] = old_files->close_on_exec_init[i]; - } - - new_files->next_fd = old_files->next_fd; - - return new_files; -} - -/* ================================================================== */ -/* alloc_fd — find lowest free fd >= start */ -/* ================================================================== */ - -int alloc_fd(files_struct* files, unsigned int start) -{ - LockGuard guard(files->file_lock); - - for (int fd = static_cast(start); fd < files->max_fds; fd++) { - if (!bit_test(files->open_fds_init, fd)) { - bit_set(files->open_fds_init, fd); - files->fd_array[fd] = nullptr; /* placeholder, fd_install sets real file */ - if (fd >= files->next_fd) - files->next_fd = fd + 1; - return fd; - } - } - - return -EMFILE; -} - -/* ================================================================== */ -/* fd_install — place a file* at a given fd */ -/* ================================================================== */ - -void fd_install(files_struct* files, int fd, file* fp) -{ - LockGuard guard(files->file_lock); - files->fd_array[fd] = fp; -} - -/* ================================================================== */ -/* fcheck — look up file by fd (no refcount bump) */ -/* ================================================================== */ - -file* fcheck(files_struct* files, int fd) -{ - if (fd < 0 || fd >= files->max_fds) return nullptr; - return files->fd_array[fd]; -} - -/* ================================================================== */ -/* close_fd */ -/* ================================================================== */ - -int close_fd(files_struct* files, int fd) -{ - file* fp; - { - LockGuard guard(files->file_lock); - if (fd < 0 || fd >= files->max_fds) return -EBADF; - - fp = files->fd_array[fd]; - if (!fp) return -EBADF; - - files->fd_array[fd] = nullptr; - bit_clear(files->open_fds_init, fd); - bit_clear(files->close_on_exec_init, fd); - } - - fput(fp); - return 0; -} - -/* ================================================================== */ -/* do_dup2 — duplicate oldfd to newfd */ -/* ================================================================== */ - -int do_dup2(files_struct* files, int oldfd, int newfd, int flags) -{ - if (oldfd == newfd) return -EINVAL; - - file* existing = nullptr; - { - LockGuard guard(files->file_lock); - - if (oldfd < 0 || oldfd >= files->max_fds) return -EBADF; - if (newfd < 0 || newfd >= files->max_fds) return -EBADF; - - file* old_fp = files->fd_array[oldfd]; - if (!old_fp) return -EBADF; - - existing = files->fd_array[newfd]; - - get_file(old_fp); - files->fd_array[newfd] = old_fp; - bit_set(files->open_fds_init, newfd); - - if (flags & O_CLOEXEC) - bit_set(files->close_on_exec_init, newfd); - else - bit_clear(files->close_on_exec_init, newfd); - } - - if (existing) - fput(existing); - - return newfd; -} - -/* ================================================================== */ -/* do_close_on_exec — close all fds with CLOEXEC set */ -/* ================================================================== */ - -void do_close_on_exec(files_struct* files) -{ - for (int fd = 0; fd < files->max_fds; fd++) { - if (bit_test(files->close_on_exec_init, fd)) { - close_fd(files, fd); - } - } -} diff --git a/fs/file_table.cc b/fs/file_table.cc deleted file mode 100644 index 06095c1..0000000 --- a/fs/file_table.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * file_table.cc — Open file allocation and reference counting - */ - -#include -#include -#include -#include -#include - -/* ================================================================== */ -/* alloc_empty_file */ -/* ================================================================== */ - -file* alloc_empty_file(int flags) -{ - auto* fp = new file{}; - if (!fp) return nullptr; - - fp->f_count.store(1); - fp->f_flags = flags; - fp->f_mode = 0; - fp->f_op = nullptr; - fp->f_mapping = nullptr; - fp->f_inode = nullptr; - fp->f_pos = 0; - fp->private_data = nullptr; - fp->f_path.mnt = nullptr; - fp->f_path.de = nullptr; - - /* Derive f_mode from O_* flags */ - int acc = flags & O_ACCMODE; - if (acc == O_RDONLY) - fp->f_mode = FMODE_READ | FMODE_CAN_READ; - else if (acc == O_WRONLY) - fp->f_mode = FMODE_WRITE | FMODE_CAN_WRITE; - else if (acc == O_RDWR) - fp->f_mode = FMODE_READ | FMODE_WRITE | FMODE_CAN_READ | FMODE_CAN_WRITE; - - fp->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; - - return fp; -} - -/* ================================================================== */ -/* get_file / fput */ -/* ================================================================== */ - -file* get_file(file* f) -{ - f->f_count.fetch_add(1); - return f; -} - -void fput(file* fp) -{ - if (!fp) return; - - int old = fp->f_count.fetch_sub(1); - if (old > 1) return; - - /* Last reference — release */ - if (fp->f_op && fp->f_op->release) - fp->f_op->release(fp->f_inode, fp); - - if (fp->f_path.de) - dput(fp->f_path.de); - - /* Future: mntput(fp->f_path.mnt) */ - - delete fp; -} - -/* ================================================================== */ -/* vfs_read / vfs_write / vfs_llseek / vfs_fstat */ -/* ================================================================== */ - -int64 vfs_read(file* fp, char* buf, uint64 count, int64* pos) -{ - if (!(fp->f_mode & FMODE_CAN_READ)) - return -EBADF; - if (!fp->f_op || !fp->f_op->read) - return -EINVAL; - - return fp->f_op->read(fp, buf, count, pos); -} - -int64 vfs_write(file* fp, const char* buf, uint64 count, int64* pos) -{ - if (!(fp->f_mode & FMODE_CAN_WRITE)) - return -EBADF; - if (!fp->f_op || !fp->f_op->write) - return -EINVAL; - - return fp->f_op->write(fp, buf, count, pos); -} - -int64 vfs_llseek(file* fp, int64 offset, int whence) -{ - if (fp->f_op && fp->f_op->llseek) - return fp->f_op->llseek(fp, offset, whence); - return generic_file_llseek(fp, offset, whence); -} - -int64 generic_file_llseek(file* fp, int64 offset, int whence) -{ - int64 new_pos; - switch (whence) { - case SEEK_SET: - new_pos = offset; - break; - case SEEK_CUR: - new_pos = fp->f_pos + offset; - break; - case SEEK_END: - new_pos = fp->f_inode->i_size + offset; - break; - default: - return -EINVAL; - } - - if (new_pos < 0) return -EINVAL; - fp->f_pos = new_pos; - return new_pos; -} - -int vfs_fstat(file* fp, kstat* stat) -{ - inode* ip = file_inode(fp); - if (!ip) return -EBADF; - - if (ip->i_op && ip->i_op->getattr) { - return ip->i_op->getattr(&fp->f_path, stat, 0, 0); - } - - generic_fillattr(ip, stat); - return 0; -} - -/* ================================================================== */ -/* path_get / path_put (simplified) */ -/* ================================================================== */ - -void path_get(const path* p) -{ - if (p->de) dget(p->de); - /* Future: mntget(p->mnt) */ -} - -void path_put(const path* p) -{ - if (p->de) dput(p->de); - /* Future: mntput(p->mnt) */ -} - -/* ================================================================== */ -/* mntget / mntput (stubs for Phase 1) */ -/* ================================================================== */ - -vfsmount* mntget(vfsmount* mnt) { return mnt; } -void mntput(vfsmount*) {} diff --git a/fs/fs_struct.cc b/fs/fs_struct.cc deleted file mode 100644 index 090819f..0000000 --- a/fs/fs_struct.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * fs_struct.cc — Per-task filesystem context (cwd, root) - */ - -#include -#include - -/* ================================================================== */ -/* alloc_fs_struct */ -/* ================================================================== */ - -fs_struct* alloc_fs_struct() -{ - auto* fs = new fs_struct{}; - if (!fs) return nullptr; - - fs->count.store(1); - fs->umask = 022; - fs->root = {nullptr, nullptr}; - fs->pwd = {nullptr, nullptr}; - - return fs; -} - -/* ================================================================== */ -/* put_fs_struct */ -/* ================================================================== */ - -void put_fs_struct(fs_struct* fs) -{ - if (!fs) return; - - int old = fs->count.fetch_sub(1); - if (old > 1) return; - - path_put(&fs->root); - path_put(&fs->pwd); - delete fs; -} - -/* ================================================================== */ -/* copy_fs_struct — for fork without CLONE_FS */ -/* ================================================================== */ - -fs_struct* copy_fs_struct(const fs_struct* old_fs) -{ - auto* fs = alloc_fs_struct(); - if (!fs) return nullptr; - - fs->umask = old_fs->umask; - - fs->root = old_fs->root; - path_get(&fs->root); - - fs->pwd = old_fs->pwd; - path_get(&fs->pwd); - - return fs; -} - -/* ================================================================== */ -/* set_fs_root / set_fs_pwd */ -/* ================================================================== */ - -void set_fs_root(fs_struct* fs, const path* p) -{ - path old_root; - { - LockGuard guard(fs->lock); - old_root = fs->root; - fs->root = *p; - path_get(p); - } - path_put(&old_root); -} - -void set_fs_pwd(fs_struct* fs, const path* p) -{ - path old_pwd; - { - LockGuard guard(fs->lock); - old_pwd = fs->pwd; - fs->pwd = *p; - path_get(p); - } - path_put(&old_pwd); -} diff --git a/fs/initramfs.cc b/fs/initramfs.cc deleted file mode 100644 index ba10a3e..0000000 --- a/fs/initramfs.cc +++ /dev/null @@ -1,285 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * initramfs.cc — Unpack embedded CPIO archive into ramfs - * - * The build system embeds a newc-format CPIO archive into the kernel - * ELF as the section .init.ramfs. The linker script exports - * __initramfs_start / __initramfs_end symbols. - * - * At boot, populate_rootfs() walks the CPIO entries and creates - * directories and files in the already-mounted ramfs root. - * - * Reference: Linux init/initramfs.c - * - * CPIO "newc" header format (110 bytes, ASCII hex fields): - * magic[6] "070701" - * ino[8] mode[8] uid[8] gid[8] nlink[8] mtime[8] - * filesize[8] devmajor[8] devminor[8] rdevmajor[8] rdevminor[8] - * namesize[8] check[8] - * filename (namesize bytes, NUL terminated, padded to 4-byte boundary) - * file data (filesize bytes, padded to 4-byte boundary) - */ - -#include -#include -#include -#include -#include -#include - -/* Linker-provided symbols for the embedded CPIO archive */ -extern "C" const char __initramfs_start[]; -extern "C" const char __initramfs_end[]; - -/* ramfs inode creation (from fs/ramfs/inode.cc) */ -extern inode* ramfs_get_inode(super_block* sb, const inode* dir, - uint32 mode, uint32 rdev); - -/* Global root dentry (from fs/vfs_init.cc) */ -extern dentry* g_root_dentry; - -/* ================================================================== */ -/* CPIO newc header parsing */ -/* ================================================================== */ - -struct cpio_header { - char magic[6]; - char ino[8]; - char mode[8]; - char uid[8]; - char gid[8]; - char nlink[8]; - char mtime[8]; - char filesize[8]; - char devmajor[8]; - char devminor[8]; - char rdevmajor[8]; - char rdevminor[8]; - char namesize[8]; - char check[8]; -}; - -static constexpr int kCpioHeaderSize = 110; - -static uint32 parse_hex8(const char* s) -{ - uint32 val = 0; - for (int i = 0; i < 8; i++) { - char c = s[i]; - uint32 nibble; - if (c >= '0' && c <= '9') nibble = c - '0'; - else if (c >= 'a' && c <= 'f') nibble = c - 'a' + 10; - else if (c >= 'A' && c <= 'F') nibble = c - 'A' + 10; - else return val; - val = (val << 4) | nibble; - } - return val; -} - -static inline uint32 align4(uint32 v) -{ - return (v + 3) & ~3U; -} - -/* ================================================================== */ -/* Path resolution helpers */ -/* ================================================================== */ - -static dentry* cpio_mkdir_p(dentry* root, const char* path, - const char** out_name) -{ - dentry* cur = root; - - while (*path == '/') path++; - - while (true) { - const char* slash = path; - while (*slash && *slash != '/') slash++; - - if (*slash == '\0') { - *out_name = path; - return cur; - } - - uint32 len = static_cast(slash - path); - - qstr name; - name.name = path; - name.len = len; - name.hash = full_name_hash(path, len); - - dentry* child = d_lookup(cur, &name); - if (!child) { - child = d_alloc(cur, &name); - if (!child) return nullptr; - - inode* ip = ramfs_get_inode(cur->d_inode->i_sb, cur->d_inode, - S_IFDIR | 0755, 0); - if (!ip) return nullptr; - - d_instantiate(child, ip); - dget(child); - inc_nlink(cur->d_inode); - } - - cur = child; - path = slash + 1; - while (*path == '/') path++; - } -} - -/* ================================================================== */ -/* populate_rootfs — the main entry point */ -/* ================================================================== */ - -void populate_rootfs() -{ - const char* p = __initramfs_start; - const char* end = __initramfs_end; - uint64 archive_size = static_cast(end - p); - - if (archive_size == 0) { - printk("[initramfs] no embedded archive found\n"); - return; - } - - printk("[initramfs] unpacking %llu bytes...\n", archive_size); - - int file_count = 0; - int dir_count = 0; - - while (p + kCpioHeaderSize <= end) { - auto* hdr = reinterpret_cast(p); - - /* Verify magic */ - if (hdr->magic[0] != '0' || hdr->magic[1] != '7' || - hdr->magic[2] != '0' || hdr->magic[3] != '7' || - hdr->magic[4] != '0' || hdr->magic[5] != '1') { - printk("[initramfs] bad cpio magic at offset %llu\n", - static_cast(p - __initramfs_start)); - break; - } - - uint32 mode = parse_hex8(hdr->mode); - uint32 filesize = parse_hex8(hdr->filesize); - uint32 namesize = parse_hex8(hdr->namesize); - - const char* name = p + kCpioHeaderSize; - uint32 name_padded = align4(kCpioHeaderSize + namesize); - const char* data = p + name_padded; - uint32 data_padded = align4(filesize); - - const char* next = p + name_padded + data_padded; - - /* Check for TRAILER!!! end-of-archive marker */ - if (namesize == 11 && name[0] == 'T' && name[1] == 'R' && - name[2] == 'A' && name[3] == 'I' && name[4] == 'L' && - name[5] == 'E' && name[6] == 'R' && name[7] == '!' && - name[8] == '!' && name[9] == '!') { - break; - } - - /* Skip "." entry */ - if (namesize == 2 && name[0] == '.' && name[1] == '\0') { - p = next; - continue; - } - - /* Resolve parent directory, creating intermediate dirs */ - const char* basename = nullptr; - dentry* parent = cpio_mkdir_p(g_root_dentry, name, &basename); - if (!parent || !basename || basename[0] == '\0') { - p = next; - continue; - } - - /* Build qstr for the final component */ - uint32 blen = 0; - while (basename[blen] && basename[blen] != '/') blen++; - - qstr bname; - bname.name = basename; - bname.len = blen; - bname.hash = full_name_hash(basename, blen); - - if (S_ISDIR(mode)) { - dentry* existing = d_lookup(parent, &bname); - if (!existing) { - dentry* de = d_alloc(parent, &bname); - if (de) { - inode* ip = ramfs_get_inode(parent->d_inode->i_sb, - parent->d_inode, - S_IFDIR | (mode & 0777), 0); - if (ip) { - d_instantiate(de, ip); - dget(de); - inc_nlink(parent->d_inode); - dir_count++; - } - } - } - } else if (S_ISREG(mode)) { - dentry* de = d_alloc(parent, &bname); - if (de) { - inode* ip = ramfs_get_inode(parent->d_inode->i_sb, - parent->d_inode, - S_IFREG | (mode & 0777), 0); - if (ip) { - d_instantiate(de, ip); - dget(de); - - /* Write file content via ramfs write path */ - if (filesize > 0 && ip->i_fop && ip->i_fop->write) { - file tmp_fp = {}; - tmp_fp.f_inode = ip; - tmp_fp.f_path.de = de; - tmp_fp.f_pos = 0; - tmp_fp.f_flags = O_WRONLY; - tmp_fp.f_count.store(1); - - int64 pos = 0; - ip->i_fop->write(&tmp_fp, data, - filesize, &pos); - } - - file_count++; - printk("[initramfs] %s (%u bytes, mode %03o)\n", - name, filesize, mode & 0777); - } - } - } else if (S_ISLNK(mode)) { - /* Symlink: file data is the target path (not NUL-terminated). - * Linux: init/initramfs.c do_symlink() */ - dentry* de = d_alloc(parent, &bname); - if (de) { - inode* ip = ramfs_get_inode(parent->d_inode->i_sb, - parent->d_inode, - S_IFLNK | 0777, 0); - if (ip) { - /* Store symlink target in inode. - * Allocate a kernel buffer and copy the target. */ - char* target = new char[filesize + 1]; - if (target) { - for (uint32 i = 0; i < filesize; i++) - target[i] = data[i]; - target[filesize] = '\0'; - ip->i_link = target; - } - - d_instantiate(de, ip); - dget(de); - file_count++; - printk("[initramfs] %s -> %s (symlink)\n", - name, target ? target : "?"); - } - } - } - - p = next; - } - - printk("[initramfs] done: %d files, %d dirs\n", - file_count, dir_count); -} diff --git a/fs/inode.cc b/fs/inode.cc deleted file mode 100644 index 1d3d006..0000000 --- a/fs/inode.cc +++ /dev/null @@ -1,166 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * inode.cc — Inode allocation, lifecycle, and generic helpers - */ - -#include -#include -#include -#include - -namespace { -lume::atomic g_next_ino{1}; -} // namespace - -/* ================================================================== */ -/* new_inode — allocate a fresh inode on a superblock */ -/* ================================================================== */ - -inode* new_inode(super_block* sb) -{ - inode* ip = nullptr; - - if (sb->s_op && sb->s_op->alloc_inode) - ip = sb->s_op->alloc_inode(sb); - else - ip = new inode{}; - - if (!ip) return nullptr; - - /* Zero-init key fields */ - ip->i_sb = sb; - ip->i_ino = g_next_ino.fetch_add(1); - ip->i_mode = 0; - ip->i_flags = 0; - ip->i_uid = 0; - ip->i_gid = 0; - ip->i_nlink = 1; - ip->i_rdev = 0; - ip->i_size = 0; - ip->i_blocks = 0; - ip->i_bytes = 0; - ip->i_blkbits = sb->s_blocksize_bits; - ip->i_generation = 0; - ip->i_state = I_NEW; - ip->i_count.store(1); - ip->i_writecount.store(0); - - ip->i_atime_sec = ip->i_mtime_sec = ip->i_ctime_sec = 0; - ip->i_atime_nsec = ip->i_mtime_nsec = ip->i_ctime_nsec = 0; - - ip->i_op = nullptr; - ip->i_fop = nullptr; - ip->i_mapping = &ip->i_data; - ip->i_private = nullptr; - ip->i_pipe = nullptr; - - /* Init embedded address_space */ - ip->i_data.host = ip; - ip->i_data.a_ops = nullptr; - ip->i_data.nrpages = 0; - ip->i_data.flags = 0; - - /* Init lists */ - list_init(&ip->i_sb_list); - list_init(&ip->i_dentry); - - /* Add to superblock's inode list */ - { - LockGuard guard(sb->s_inode_list_lock); - list_add_tail(&ip->i_sb_list, &sb->s_inodes); - } - - return ip; -} - -/* ================================================================== */ -/* ihold / iput — reference counting */ -/* ================================================================== */ - -void ihold(inode* ip) -{ - ip->i_count.fetch_add(1); -} - -void iput(inode* ip) -{ - if (!ip) return; - - int old = ip->i_count.fetch_sub(1); - if (old > 1) return; - - /* Last reference dropped — evict */ - if (ip->i_sb->s_op && ip->i_sb->s_op->evict_inode) - ip->i_sb->s_op->evict_inode(ip); - - /* Remove from sb list */ - { - LockGuard guard(ip->i_sb->s_inode_list_lock); - list_del(&ip->i_sb_list); - } - - if (ip->i_sb->s_op && ip->i_sb->s_op->destroy_inode) - ip->i_sb->s_op->destroy_inode(ip); - else - delete ip; -} - -/* ================================================================== */ -/* nlink helpers */ -/* ================================================================== */ - -void set_nlink(inode* ip, uint32 nlink) { ip->i_nlink = nlink; } -void inc_nlink(inode* ip) { ip->i_nlink++; } -void drop_nlink(inode* ip) { ip->i_nlink--; } -void clear_nlink(inode* ip) { ip->i_nlink = 0; } - -/* ================================================================== */ -/* inode_init_owner */ -/* ================================================================== */ - -void inode_init_owner(inode* ip, const inode* dir, uint32 mode) -{ - ip->i_uid = 0; /* Phase 1: always root */ - ip->i_gid = 0; - ip->i_mode = mode; -} - -/* ================================================================== */ -/* generic_fillattr — fill kstat from inode (used by getattr) */ -/* ================================================================== */ - -void generic_fillattr(inode* ip, kstat* stat) -{ - stat->st_dev = ip->i_sb->s_dev; - stat->st_ino = ip->i_ino; - stat->st_mode = ip->i_mode; - stat->st_nlink = ip->i_nlink; - stat->st_uid = ip->i_uid; - stat->st_gid = ip->i_gid; - stat->st_rdev = ip->i_rdev; - stat->__pad = 0; - stat->st_size = ip->i_size; - stat->st_blksize = 1 << ip->i_blkbits; - stat->__pad2 = 0; - stat->st_blocks = ip->i_blocks; - stat->st_atime_sec = ip->i_atime_sec; - stat->st_atime_nsec = ip->i_atime_nsec; - stat->st_mtime_sec = ip->i_mtime_sec; - stat->st_mtime_nsec = ip->i_mtime_nsec; - stat->st_ctime_sec = ip->i_ctime_sec; - stat->st_ctime_nsec = ip->i_ctime_nsec; - stat->__unused[0] = 0; - stat->__unused[1] = 0; -} - -/* ================================================================== */ -/* mark_inode_dirty (stub) */ -/* ================================================================== */ - -void mark_inode_dirty(inode* ip) -{ - ip->i_state |= I_DIRTY_SYNC; - /* Phase 1: no writeback, ramfs is memory-only */ -} diff --git a/fs/namei.cc b/fs/namei.cc deleted file mode 100644 index 9124ea9..0000000 --- a/fs/namei.cc +++ /dev/null @@ -1,250 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * namei.cc — Pathname resolution (path lookup) - * - * Simplified Phase 1: no symlink, no RCU, no mount traversal. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ================================================================== */ -/* Helpers */ -/* ================================================================== */ - -static const char* next_component(const char* path, qstr* result) -{ - while (*path == '/') path++; - if (*path == '\0') return nullptr; - - const char* start = path; - while (*path != '\0' && *path != '/') path++; - - uint32 len = static_cast(path - start); - result->name = start; - result->len = len; - result->hash = full_name_hash(start, len); - - return path; -} - -static bool is_dot(const qstr* name) { - return name->len == 1 && name->name[0] == '.'; -} -static bool is_dotdot(const qstr* name) { - return name->len == 2 && name->name[0] == '.' && name->name[1] == '.'; -} - -/* ================================================================== */ -/* walk_component */ -/* ================================================================== */ - -static dentry* walk_component(dentry* parent, const qstr* name) -{ - if (!parent->d_inode || !S_ISDIR(parent->d_inode->i_mode)) - return reinterpret_cast(-ENOTDIR); - - if (is_dot(name)) - return dget(parent); - - if (is_dotdot(name)) - return dget(parent->d_parent); - - /* Try dcache */ - dentry* child = d_lookup(parent, name); - if (child) - return child; - - /* Cache miss — call filesystem lookup */ - inode* dir = parent->d_inode; - if (!dir->i_op || !dir->i_op->lookup) - return reinterpret_cast(-ENOENT); - - child = d_alloc(parent, name); - if (!child) - return reinterpret_cast(-ENOMEM); - - dentry* result = dir->i_op->lookup(dir, child, 0); - if (result) { - dput(child); - return result; - } - - /* If lookup didn't set an inode, this is a negative dentry - * (file doesn't exist). Remove from dcache and return error. */ - if (!child->d_inode) { - d_drop(child); - dput(child); - return reinterpret_cast(-ENOENT); - } - - return child; -} - -/* ================================================================== */ -/* filename_lookup */ -/* ================================================================== */ - -int filename_lookup(int dfd, const char* name, unsigned int flags, path* result) -{ - if (!name || !result) - return -EINVAL; - - TaskControlBlock* task = current_task(); - dentry* start; - - /* Determine starting dentry */ - if (name[0] == '/') { - start = task->fs->root.de; - if (!start) start = g_root_dentry; - name++; - } else if (dfd == AT_FDCWD) { - start = task->fs->pwd.de; - if (!start) start = g_root_dentry; - } else { - file* dir_fp = fcheck(task->files, dfd); - if (!dir_fp) return -EBADF; - start = dir_fp->f_path.de; - if (!start || !start->d_inode || !S_ISDIR(start->d_inode->i_mode)) - return -ENOTDIR; - } - - dentry* current_de = dget(start); - const char* p = name; - - while (p && *p) { - qstr component; - const char* next = next_component(p, &component); - if (!next && component.len == 0) - break; - - const char* after = next; - while (after && *after == '/') after++; - bool is_last = (!after || *after == '\0'); - - if (is_last && (flags & LOOKUP_PARENT)) { - result->de = current_de; - result->mnt = task->fs->root.mnt; - return 0; - } - - dentry* child = walk_component(current_de, &component); - - int64 err = reinterpret_cast(child); - if (err < 0 && err >= -4095) { - dput(current_de); - return static_cast(err); - } - - /* ---- Symlink following (Linux: step_into → pick_link) ---- - * If the resolved component is a symlink, follow it. - * Linux limits this to MAXSYMLINKS (40); we use 8. */ - constexpr int kMaxSymlinks = 8; - int symlink_depth = 0; - while (child->d_inode && S_ISLNK(child->d_inode->i_mode) && - child->d_inode->i_link && symlink_depth < kMaxSymlinks) { - symlink_depth++; - const char* target = child->d_inode->i_link; - dput(child); - - /* Absolute symlink: restart from root. - * Relative symlink: resolve from current parent. */ - dentry* link_start; - if (target[0] == '/') { - link_start = dget(task->fs->root.de ? task->fs->root.de : g_root_dentry); - target++; - } else { - link_start = dget(current_de); - } - - /* Walk each component of the symlink target */ - dentry* link_cur = link_start; - const char* lp = target; - qstr lcomp; - while (lp && *lp) { - const char* lnext = next_component(lp, &lcomp); - if (!lnext && lcomp.len == 0) break; - - dentry* lchild = walk_component(link_cur, &lcomp); - int64 lerr = reinterpret_cast(lchild); - if (lerr < 0 && lerr >= -4095) { - dput(link_cur); - dput(current_de); - return static_cast(lerr); - } - - dput(link_cur); - link_cur = lchild; - lp = lnext; - } - - child = link_cur; - } - - if (symlink_depth >= kMaxSymlinks) { - dput(child); - dput(current_de); - return -ELOOP; - } - - if (!is_last && child->d_inode && !S_ISDIR(child->d_inode->i_mode)) { - dput(child); - dput(current_de); - return -ENOTDIR; - } - - if (!is_last && !child->d_inode) { - dput(child); - dput(current_de); - return -ENOENT; - } - - dput(current_de); - current_de = child; - p = next; - } - - if ((flags & LOOKUP_DIRECTORY) && current_de->d_inode && - !S_ISDIR(current_de->d_inode->i_mode)) { - dput(current_de); - return -ENOTDIR; - } - - /* Negative dentry: the path was walked, but the final component - * does not exist (d_inode == NULL). Return -ENOENT. */ - if (!current_de->d_inode) { - dput(current_de); - return -ENOENT; - } - - result->de = current_de; - result->mnt = task->fs->root.mnt; - return 0; -} - -int kern_path(const char* name, unsigned int flags, path* result) -{ - return filename_lookup(AT_FDCWD, name, flags, result); -} - -dentry* lookup_one_len(const char* name, dentry* parent, int len) -{ - qstr q; - q.name = name; - q.len = static_cast(len); - q.hash = full_name_hash(name, q.len); - - return walk_component(parent, &q); -} - -void namei_init() {} diff --git a/fs/pipe.cc b/fs/pipe.cc deleted file mode 100644 index f7708f5..0000000 --- a/fs/pipe.cc +++ /dev/null @@ -1,278 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * pipe.cc — Pipe implementation - * - * Implements unidirectional byte-stream pipes with blocking I/O. - * Each pipe has a 4KB circular buffer. Reads block when empty, - * writes block when full (unless O_NONBLOCK). - * - * When all writers close, read returns 0 (EOF). - * When all readers close, write returns -EPIPE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* ================================================================== */ -/* pipe_inode_info lifecycle */ -/* ================================================================== */ - -pipe_inode_info* alloc_pipe_info() -{ - auto* pi = new pipe_inode_info{}; - if (!pi) return nullptr; - - pi->rd_pos = 0; - pi->wr_pos = 0; - pi->len = 0; - pi->rd_wait.init("pipe_rd"); - pi->wr_wait.init("pipe_wr"); - pi->readers.store(0); - pi->writers.store(0); - pi->refcount.store(1); - return pi; -} - -void free_pipe_info(pipe_inode_info* pipe) -{ - delete pipe; -} - -static void pipe_get(pipe_inode_info* pi) -{ - pi->refcount.fetch_add(1); -} - -static void pipe_put(pipe_inode_info* pi) -{ - if (pi->refcount.fetch_sub(1) == 1) { - free_pipe_info(pi); - } -} - -/* ================================================================== */ -/* pipe_read */ -/* ================================================================== */ - -static int64 pipe_read(file* fp, char* buf, uint64 count, int64* /*pos*/) -{ - pipe_inode_info* pi = static_cast(fp->private_data); - if (!pi) return -EBADF; - - while (true) { - pi->lock.acquire(); - - if (pi->len > 0) { - /* Data available — copy out */ - int64 to_read = static_cast(count); - if (to_read > pi->len) to_read = pi->len; - - for (int64 i = 0; i < to_read; i++) { - buf[i] = pi->buf[pi->rd_pos]; - pi->rd_pos = (pi->rd_pos + 1) % PIPE_BUF_SIZE; - } - pi->len -= static_cast(to_read); - - pi->lock.release(); - - /* Wake any blocked writers */ - pi->wr_wait.wake_all(); - return to_read; - } - - /* Buffer empty */ - if (pi->writers.load() == 0) { - /* No writers left — EOF */ - pi->lock.release(); - return 0; - } - - if (fp->f_flags & O_NONBLOCK) { - pi->lock.release(); - return -EAGAIN; - } - - pi->lock.release(); - - /* Sleep until data or writer closes */ - pi->rd_wait.sleep(); - } -} - -/* ================================================================== */ -/* pipe_write */ -/* ================================================================== */ - -static int64 pipe_write(file* fp, const char* buf, uint64 count, int64* /*pos*/) -{ - pipe_inode_info* pi = static_cast(fp->private_data); - if (!pi) return -EBADF; - - if (pi->readers.load() == 0) { - return -EPIPE; /* Broken pipe */ - } - - int64 written = 0; - - while (static_cast(written) < count) { - pi->lock.acquire(); - - if (pi->len < PIPE_BUF_SIZE) { - /* Space available — copy in */ - int avail = PIPE_BUF_SIZE - pi->len; - int64 remaining = static_cast(count) - written; - int to_write = avail < static_cast(remaining) - ? avail - : static_cast(remaining); - - for (int i = 0; i < to_write; i++) { - pi->buf[pi->wr_pos] = buf[written + i]; - pi->wr_pos = (pi->wr_pos + 1) % PIPE_BUF_SIZE; - } - pi->len += to_write; - written += to_write; - - pi->lock.release(); - - /* Wake any blocked readers */ - pi->rd_wait.wake_all(); - continue; - } - - /* Buffer full */ - if (pi->readers.load() == 0) { - pi->lock.release(); - return written > 0 ? written : -EPIPE; - } - - if (fp->f_flags & O_NONBLOCK) { - pi->lock.release(); - return written > 0 ? written : -EAGAIN; - } - - pi->lock.release(); - - /* Sleep until space or reader closes */ - pi->wr_wait.sleep(); - } - - return written; -} - -/* ================================================================== */ -/* pipe_release — called on last fput of a pipe fd */ -/* ================================================================== */ - -static int pipe_read_release(inode* /*ip*/, file* fp) -{ - pipe_inode_info* pi = static_cast(fp->private_data); - if (pi) { - pi->readers.fetch_sub(1); - /* Wake writers so they see readers==0 and get EPIPE */ - pi->wr_wait.wake_all(); - pipe_put(pi); - } - return 0; -} - -static int pipe_write_release(inode* /*ip*/, file* fp) -{ - pipe_inode_info* pi = static_cast(fp->private_data); - if (pi) { - pi->writers.fetch_sub(1); - /* Wake readers so they see writers==0 and get EOF */ - pi->rd_wait.wake_all(); - pipe_put(pi); - } - return 0; -} - -/* ================================================================== */ -/* file_operations tables */ -/* ================================================================== */ - -static file_operations pipe_read_fops; -static file_operations pipe_write_fops; -static bool pipe_fops_initialized = false; - -static void pipe_fops_init() -{ - if (pipe_fops_initialized) return; - - pipe_read_fops = {}; - pipe_read_fops.read = pipe_read; - pipe_read_fops.release = pipe_read_release; - - pipe_write_fops = {}; - pipe_write_fops.write = pipe_write; - pipe_write_fops.release = pipe_write_release; - - pipe_fops_initialized = true; -} - -/* ================================================================== */ -/* do_pipe2 — create a pipe, install two fds */ -/* ================================================================== */ - -int do_pipe2(files_struct* files, int fds[2], int flags) -{ - pipe_fops_init(); - - pipe_inode_info* pi = alloc_pipe_info(); - if (!pi) return -ENOMEM; - - /* Create read-end file */ - file* rd_fp = alloc_empty_file(O_RDONLY | (flags & O_NONBLOCK)); - if (!rd_fp) { - free_pipe_info(pi); - return -ENFILE; - } - rd_fp->f_op = &pipe_read_fops; - rd_fp->private_data = pi; - - /* Create write-end file */ - file* wr_fp = alloc_empty_file(O_WRONLY | (flags & O_NONBLOCK)); - if (!wr_fp) { - fput(rd_fp); - free_pipe_info(pi); - return -ENFILE; - } - wr_fp->f_op = &pipe_write_fops; - wr_fp->private_data = pi; - - /* Bump pipe refcount for the two files */ - pipe_get(pi); /* wr_fp gets second ref */ - pi->readers.store(1); - pi->writers.store(1); - - /* Allocate fds */ - int rd_fd = alloc_fd(files, 0); - if (rd_fd < 0) { - fput(rd_fp); - fput(wr_fp); - return rd_fd; - } - - int wr_fd = alloc_fd(files, 0); - if (wr_fd < 0) { - close_fd(files, rd_fd); - fput(wr_fp); - return wr_fd; - } - - fd_install(files, rd_fd, rd_fp); - fd_install(files, wr_fd, wr_fp); - - fds[0] = rd_fd; - fds[1] = wr_fd; - - return 0; -} diff --git a/fs/ramfs/file.cc b/fs/ramfs/file.cc deleted file mode 100644 index 6d9a070..0000000 --- a/fs/ramfs/file.cc +++ /dev/null @@ -1,216 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * ramfs/file.cc — RamFS file operations (read/write via in-memory pages) - * - * Phase 1: simple flat buffer per-inode via i_private. - * Will migrate to page_cache integration later. - */ - -#include -#include -#include -#include -#include -#include - -/* - * Simplest possible in-memory file storage: - * i_private points to a dynamically grown buffer. - */ -struct ramfs_file_data { - char* buf; - uint64 capacity; -}; - -static ramfs_file_data* get_or_create_data(inode* ip) -{ - if (!ip->i_private) { - auto* data = new ramfs_file_data{}; - data->buf = nullptr; - data->capacity = 0; - ip->i_private = data; - } - return static_cast(ip->i_private); -} - -static int ensure_capacity(ramfs_file_data* data, uint64 needed) -{ - if (needed <= data->capacity) return 0; - - /* Round up to page size */ - uint64 new_cap = (needed + 4095) & ~4095ULL; - char* new_buf = new char[new_cap]; - if (!new_buf) return -ENOMEM; - - /* Copy old data */ - if (data->buf && data->capacity > 0) { - for (uint64 i = 0; i < data->capacity; i++) - new_buf[i] = data->buf[i]; - } - /* Zero new region */ - for (uint64 i = data->capacity; i < new_cap; i++) - new_buf[i] = 0; - - delete[] data->buf; - data->buf = new_buf; - data->capacity = new_cap; - return 0; -} - -/* ================================================================== */ -/* ramfs_read */ -/* ================================================================== */ - -static int64 ramfs_read(file* fp, char* buf, uint64 count, int64* pos) -{ - inode* ip = file_inode(fp); - int64 offset = *pos; - - if (offset < 0) return -EINVAL; - if (offset >= ip->i_size) return 0; - - int64 avail = ip->i_size - offset; - if (static_cast(count) > avail) - count = static_cast(avail); - - auto* data = static_cast(ip->i_private); - if (!data || !data->buf) return 0; - - /* Copy to user buffer. - * TODO: use copy_to_user when called from syscall context */ - for (uint64 i = 0; i < count; i++) - buf[i] = data->buf[offset + i]; - - *pos += count; - return static_cast(count); -} - -/* ================================================================== */ -/* ramfs_write */ -/* ================================================================== */ - -static int64 ramfs_write(file* fp, const char* buf, uint64 count, int64* pos) -{ - inode* ip = file_inode(fp); - int64 offset = *pos; - - if (fp->f_flags & O_APPEND) - offset = ip->i_size; - - if (offset < 0) return -EINVAL; - - auto* data = get_or_create_data(ip); - uint64 end = static_cast(offset) + count; - - int err = ensure_capacity(data, end); - if (err) return err; - - /* Copy from user buffer */ - for (uint64 i = 0; i < count; i++) - data->buf[offset + i] = buf[i]; - - if (static_cast(end) > ip->i_size) - ip->i_size = end; - - *pos = end; - mark_inode_dirty(ip); - return static_cast(count); -} - -/* ================================================================== */ -/* ramfs_dir_iterate — getdents64 */ -/* ================================================================== */ - -static int ramfs_dir_iterate(file* fp, dir_context* ctx) -{ - dentry* dir_de = file_dentry(fp); - inode* dir_ip = file_inode(fp); - int64 pos = ctx->pos; - int count = 0; - - /* pos 0: emit "." */ - if (pos == 0) { - if (!ctx->actor(ctx, ".", 1, pos, dir_ip->i_ino, DT_DIR)) - return 0; - ctx->pos = 1; - pos = 1; - count++; - } - - /* pos 1: emit ".." */ - if (pos == 1) { - uint64 parent_ino = dir_de->d_parent->d_inode - ? dir_de->d_parent->d_inode->i_ino : dir_ip->i_ino; - if (!ctx->actor(ctx, "..", 2, pos, parent_ino, DT_DIR)) - return 0; - ctx->pos = 2; - pos = 2; - count++; - } - - /* pos >= 2: iterate children */ - int64 child_idx = 2; - list_node* node; - list_for_each(node, &dir_de->d_children) { - dentry* child = list_entry(node, dentry, d_child); - - if (!child->d_inode) - continue; /* skip negative dentries */ - - if (child_idx >= pos) { - uint8 d_type = DT_UNKNOWN; - if (S_ISDIR(child->d_inode->i_mode)) d_type = DT_DIR; - else if (S_ISREG(child->d_inode->i_mode)) d_type = DT_REG; - else if (S_ISCHR(child->d_inode->i_mode)) d_type = DT_CHR; - else if (S_ISBLK(child->d_inode->i_mode)) d_type = DT_BLK; - else if (S_ISLNK(child->d_inode->i_mode)) d_type = DT_LNK; - else if (S_ISFIFO(child->d_inode->i_mode)) d_type = DT_FIFO; - - if (!ctx->actor(ctx, child->d_name.name, - static_cast(child->d_name.len), - child_idx, child->d_inode->i_ino, d_type)) - return 0; - - ctx->pos = child_idx + 1; - count++; - } - child_idx++; - } - - return count; -} - -extern file_operations ramfs_file_operations; -extern file_operations ramfs_dir_operations; - -file_operations ramfs_file_operations; -file_operations ramfs_dir_operations; - -void ramfs_file_ops_init() -{ - ramfs_file_operations.llseek = nullptr; - ramfs_file_operations.read = ramfs_read; - ramfs_file_operations.write = ramfs_write; - ramfs_file_operations.iterate_shared = nullptr; - ramfs_file_operations.poll = nullptr; - ramfs_file_operations.unlocked_ioctl = nullptr; - ramfs_file_operations.mmap = nullptr; - ramfs_file_operations.open = nullptr; - ramfs_file_operations.flush = nullptr; - ramfs_file_operations.release = nullptr; - ramfs_file_operations.fsync = nullptr; - - ramfs_dir_operations.llseek = nullptr; - ramfs_dir_operations.read = nullptr; - ramfs_dir_operations.write = nullptr; - ramfs_dir_operations.iterate_shared = ramfs_dir_iterate; - ramfs_dir_operations.poll = nullptr; - ramfs_dir_operations.unlocked_ioctl = nullptr; - ramfs_dir_operations.mmap = nullptr; - ramfs_dir_operations.open = nullptr; - ramfs_dir_operations.flush = nullptr; - ramfs_dir_operations.release = nullptr; - ramfs_dir_operations.fsync = nullptr; -} diff --git a/fs/ramfs/inode.cc b/fs/ramfs/inode.cc deleted file mode 100644 index c5e49bf..0000000 --- a/fs/ramfs/inode.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * ramfs/inode.cc — RamFS inode operations - * - * A simple in-memory filesystem (like Linux tmpfs without swap). - * All data lives in memory via the page cache. - */ - -#include -#include -#include -#include -#include -#include - -/* Forward declarations */ -extern file_operations ramfs_file_operations; -extern file_operations ramfs_dir_operations; -extern inode_operations ramfs_dir_inode_operations; - -/* ================================================================== */ -/* ramfs_get_inode — allocate + init an inode for ramfs */ -/* ================================================================== */ - -inode* ramfs_get_inode(super_block* sb, const inode* dir, uint32 mode, uint32 rdev) -{ - inode* ip = new_inode(sb); - if (!ip) return nullptr; - - inode_init_owner(ip, dir, mode); - /* TODO: set timestamps to current time when we have a time source */ - - switch (mode & S_IFMT) { - case S_IFREG: - ip->i_op = nullptr; /* regular files don't need inode_ops for Phase 1 */ - ip->i_fop = &ramfs_file_operations; - break; - case S_IFDIR: - ip->i_op = &ramfs_dir_inode_operations; - ip->i_fop = &ramfs_dir_operations; - inc_nlink(ip); /* directories start with nlink=2 (. and parent's link) */ - break; - case S_IFLNK: - /* Symlink: stub for Phase 1 */ - break; - default: - /* Character/block devices: i_rdev */ - ip->i_rdev = rdev; - break; - } - - return ip; -} - -/* ================================================================== */ -/* Directory inode operations */ -/* ================================================================== */ - -static dentry* ramfs_lookup(inode* dir, dentry* de, unsigned int flags) -{ - (void)dir; - (void)flags; - /* For ramfs, everything is in dcache. If we get here, it means - * d_lookup() already failed, so this is a negative dentry. - * Just return nullptr to let the caller see de->d_inode == NULL. */ - return nullptr; -} - -static int ramfs_create(inode* dir, dentry* de, uint32 mode, bool excl) -{ - (void)excl; - inode* ip = ramfs_get_inode(dir->i_sb, dir, mode | S_IFREG, 0); - if (!ip) return -ENOMEM; - - d_instantiate(de, ip); - dget(de); - dir->i_size += de->d_name.len; - mark_inode_dirty(dir); - return 0; -} - -static int ramfs_mkdir(inode* dir, dentry* de, uint32 mode) -{ - inode* ip = ramfs_get_inode(dir->i_sb, dir, mode | S_IFDIR, 0); - if (!ip) return -ENOMEM; - - d_instantiate(de, ip); - dget(de); - inc_nlink(dir); - dir->i_size += de->d_name.len; - mark_inode_dirty(dir); - return 0; -} - -static int ramfs_rmdir(inode* dir, dentry* de) -{ - /* Check if directory is empty */ - if (!list_empty(&de->d_children)) - return -ENOTEMPTY; - - drop_nlink(de->d_inode); /* remove . link */ - drop_nlink(de->d_inode); /* remove parent's link */ - drop_nlink(dir); - d_delete(de); - dir->i_size -= de->d_name.len; - mark_inode_dirty(dir); - return 0; -} - -static int ramfs_unlink(inode* dir, dentry* de) -{ - drop_nlink(de->d_inode); - d_delete(de); - dir->i_size -= de->d_name.len; - mark_inode_dirty(dir); - return 0; -} - -static int ramfs_link(dentry* old_de, inode* dir, dentry* new_de) -{ - inode* ip = old_de->d_inode; - if (!ip) return -ENOENT; - - inc_nlink(ip); - ihold(ip); - d_instantiate(new_de, ip); - dget(new_de); - dir->i_size += new_de->d_name.len; - mark_inode_dirty(dir); - return 0; -} - -static int ramfs_mknod(inode* dir, dentry* de, uint32 mode, uint32 rdev) -{ - inode* ip = ramfs_get_inode(dir->i_sb, dir, mode, rdev); - if (!ip) return -ENOMEM; - - d_instantiate(de, ip); - dget(de); - dir->i_size += de->d_name.len; - mark_inode_dirty(dir); - return 0; -} - -inode_operations ramfs_dir_inode_operations; - -void ramfs_dir_inode_ops_init() -{ - ramfs_dir_inode_operations.lookup = ramfs_lookup; - ramfs_dir_inode_operations.create = ramfs_create; - ramfs_dir_inode_operations.link = ramfs_link; - ramfs_dir_inode_operations.unlink = ramfs_unlink; - ramfs_dir_inode_operations.symlink = nullptr; - ramfs_dir_inode_operations.mkdir = ramfs_mkdir; - ramfs_dir_inode_operations.rmdir = ramfs_rmdir; - ramfs_dir_inode_operations.mknod = ramfs_mknod; - ramfs_dir_inode_operations.rename = nullptr; - ramfs_dir_inode_operations.setattr = nullptr; - ramfs_dir_inode_operations.getattr = nullptr; - ramfs_dir_inode_operations.get_link = nullptr; - ramfs_dir_inode_operations.permission = nullptr; -} diff --git a/fs/ramfs/super.cc b/fs/ramfs/super.cc deleted file mode 100644 index 6f929f2..0000000 --- a/fs/ramfs/super.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * ramfs/super.cc — RamFS superblock: mount, fill_super, and init - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -extern inode* ramfs_get_inode(super_block* sb, const inode* dir, - uint32 mode, uint32 rdev); - -/* Superblock allocation helper (defined in super.cc) */ -extern super_block* alloc_super(file_system_type* type); - -/* ================================================================== */ -/* ramfs super_operations */ -/* ================================================================== */ - -static inode* ramfs_alloc_inode(super_block* sb) -{ - return new inode{}; -} - -static void ramfs_destroy_inode(inode* ip) -{ - /* Free ramfs_file_data if any */ - if (ip->i_private) { - struct ramfs_file_data { - char* buf; - uint64 capacity; - }; - auto* data = static_cast(ip->i_private); - delete[] data->buf; - delete data; - } - delete ip; -} - -static int ramfs_statfs(dentry* de, kstatfs* buf) -{ - /* Simple fake values */ - buf->f_type = 0x858458f6; /* RAMFS_MAGIC */ - buf->f_bsize = 4096; - buf->f_blocks = 0; - buf->f_bfree = 0; - buf->f_bavail = 0; - buf->f_files = 0; - buf->f_ffree = 0; - buf->f_namelen = 255; - buf->f_frsize = 4096; - buf->f_flags = 0; - return 0; -} - -static super_operations ramfs_sops; - -static void ramfs_sops_init() -{ - ramfs_sops.alloc_inode = ramfs_alloc_inode; - ramfs_sops.destroy_inode = ramfs_destroy_inode; - ramfs_sops.free_inode = nullptr; - ramfs_sops.dirty_inode = nullptr; - ramfs_sops.write_inode = nullptr; - ramfs_sops.drop_inode = nullptr; - ramfs_sops.evict_inode = nullptr; - ramfs_sops.put_super = nullptr; - ramfs_sops.sync_fs = nullptr; - ramfs_sops.statfs = ramfs_statfs; - ramfs_sops.umount_begin = nullptr; -} - -/* ================================================================== */ -/* ramfs_fill_super */ -/* ================================================================== */ - -static int ramfs_fill_super(super_block* sb, void* data, int silent) -{ - sb->s_op = &ramfs_sops; - sb->s_magic = 0x858458f6; - sb->s_blocksize = 4096; - sb->s_blocksize_bits = 12; - sb->s_maxbytes = 0x7FFFFFFFFFFFFFFFLL; - sb->s_time_gran = 1; - - /* Create root inode */ - inode* root_ip = ramfs_get_inode(sb, nullptr, S_IFDIR | 0755, 0); - if (!root_ip) return -ENOMEM; - - /* Create root dentry */ - sb->s_root = d_make_root(root_ip); - if (!sb->s_root) - return -ENOMEM; - - return 0; -} - -/* ================================================================== */ -/* ramfs_mount */ -/* ================================================================== */ - -static super_block* ramfs_mount(file_system_type* type, int flags, - const char* dev_name, void* data) -{ - super_block* sb = alloc_super(type); - if (!sb) return nullptr; - - int err = ramfs_fill_super(sb, data, flags & SB_SILENT); - if (err) { - delete sb; - return nullptr; - } - - return sb; -} - -static void ramfs_kill_sb(super_block* sb) -{ - /* Phase 1: no cleanup needed for ramfs */ - (void)sb; -} - -/* ================================================================== */ -/* Filesystem type registration */ -/* ================================================================== */ - -static file_system_type ramfs_fs_type; - -extern void ramfs_file_ops_init(); -extern void ramfs_dir_inode_ops_init(); - -void ramfs_init() -{ - /* Runtime init to avoid un-relocated absolute pointers in .data */ - ramfs_sops_init(); - ramfs_file_ops_init(); - ramfs_dir_inode_ops_init(); - - ramfs_fs_type.name = "ramfs"; - ramfs_fs_type.fs_flags = FS_NO_DEVICE; - ramfs_fs_type.mount = ramfs_mount; - ramfs_fs_type.kill_sb = ramfs_kill_sb; - list_init(&ramfs_fs_type.fs_list); - - register_filesystem(&ramfs_fs_type); -} - diff --git a/fs/super.cc b/fs/super.cc deleted file mode 100644 index 231b57c..0000000 --- a/fs/super.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * super.cc — Superblock lifecycle + filesystem type registry - */ - -#include -#include -#include -#include -#include -#include - -/* Global root filesystem entry points */ -vfsmount* g_root_mnt = nullptr; -dentry* g_root_dentry = nullptr; - -/* ================================================================== */ -/* Filesystem type registry */ -/* ================================================================== */ - -namespace { - -list_head g_fs_types; -Spinlock g_fs_type_lock; - -} // namespace - -int register_filesystem(file_system_type* fs) -{ - LockGuard guard(g_fs_type_lock); - list_add_tail(&fs->fs_list, &g_fs_types); - printk("[vfs] registered filesystem: %s\n", fs->name); - return 0; -} - -file_system_type* get_fs_type(const char* name) -{ - LockGuard guard(g_fs_type_lock); - list_node* pos; - list_for_each(pos, &g_fs_types) { - auto* fs = list_entry(pos, file_system_type, fs_list); - /* Simple strcmp */ - const char* a = fs->name; - const char* b = name; - while (*a && *a == *b) { a++; b++; } - if (*a == '\0' && *b == '\0') - return fs; - } - return nullptr; -} - -/* ================================================================== */ -/* Superblock allocation */ -/* ================================================================== */ - -super_block* alloc_super(file_system_type* type) -{ - auto* sb = new super_block{}; - if (!sb) return nullptr; - - list_init(&sb->s_list); - list_init(&sb->s_inodes); - sb->s_type = type; - sb->s_op = nullptr; - sb->s_root = nullptr; - sb->s_fs_info = nullptr; - sb->s_blocksize = 4096; - sb->s_blocksize_bits = 12; - sb->s_maxbytes = 0x7FFFFFFFFFFFFFFFLL; - sb->s_time_gran = 1; - sb->s_time_min = 0; - sb->s_time_max = 0x7FFFFFFFFFFFFFFFLL; - sb->s_flags = 0; - sb->s_magic = 0; - sb->s_active.store(1); - sb->s_count = 1; - sb->s_max_links = 0; - sb->s_d_op = nullptr; - sb->s_mounts = nullptr; - sb->s_dev = 0; - for (int i = 0; i < 32; i++) sb->s_id[i] = 0; - - return sb; -} - -/* ================================================================== */ -/* Init */ -/* ================================================================== */ - -void super_init() -{ - list_init(&g_fs_types); -} diff --git a/fs/vfs_init.cc b/fs/vfs_init.cc deleted file mode 100644 index ec56e88..0000000 --- a/fs/vfs_init.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * vfs_init.cc — Bootstrap the VFS: mount ramfs root, set global root - * - * Called from kernel_main() after slab_init() and ramfs_init(). - * This is the moral equivalent of Linux's vfs_caches_init() + - * mnt_init() + init_rootfs(). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ================================================================== */ -/* vfs_init — mount ramfs as root filesystem */ -/* ================================================================== */ - -/* - * ramfs_mount is called internally via the file_system_type::mount - * callback registered by ramfs_init(). We look it up by name. - */ -extern file_system_type* get_fs_type(const char* name); -extern super_block* alloc_super(file_system_type* type); - -void vfs_init() -{ - /* 1. Look up the ramfs filesystem type */ - file_system_type* ramfs_type = get_fs_type("ramfs"); - if (!ramfs_type || !ramfs_type->mount) { - printk(KERN_ERR "vfs_init: ramfs not registered!\n"); - return; - } - - /* 2. Mount ramfs */ - super_block* sb = ramfs_type->mount(ramfs_type, 0, "ramfs", nullptr); - if (!sb || !sb->s_root) { - printk(KERN_ERR "vfs_init: failed to mount ramfs!\n"); - return; - } - - /* 3. Set global root */ - g_root_dentry = sb->s_root; - g_root_mnt = nullptr; /* TODO: allocate a proper vfsmount when mount.cc lands */ - - dget(g_root_dentry); /* Hold a reference for the global root */ - - printk(KERN_INFO "[vfs] root filesystem mounted (ramfs)\n"); - - /* 4. Set up VFS state for the current (BSP idle) task, - * which will be inherited by all subsequently created tasks. */ - TaskControlBlock* bsp = current_task(); - if (bsp) { - if (!bsp->files) { - bsp->files = alloc_files_struct(); - } - if (!bsp->fs) { - bsp->fs = alloc_fs_struct(); - if (bsp->fs) { - bsp->fs->root.de = g_root_dentry; - bsp->fs->root.mnt = g_root_mnt; - bsp->fs->pwd.de = g_root_dentry; - bsp->fs->pwd.mnt = g_root_mnt; - dget(g_root_dentry); /* root ref */ - dget(g_root_dentry); /* pwd ref */ - } - } - printk(KERN_INFO "[vfs] BSP task VFS context initialized\n"); - } -} -- cgit v1.2.3