diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
| commit | e90b72ec3082588b296956730bd2930cf8d5d671 (patch) | |
| tree | 36ff6916af9b4176ea5a9662219d11e721f0b691 /lume-legacy/src/fs/fs.cc | |
| parent | 1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff) | |
| download | lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz | |
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'lume-legacy/src/fs/fs.cc')
| -rw-r--r-- | lume-legacy/src/fs/fs.cc | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/lume-legacy/src/fs/fs.cc b/lume-legacy/src/fs/fs.cc new file mode 100644 index 0000000..fc8f555 --- /dev/null +++ b/lume-legacy/src/fs/fs.cc @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 Richard QIn + */ +#include "fs/fs.h" +#include "kernel/riscv.h" +#include "drivers/uart.h" +#include "kernel/spinlock.h" +#include "kernel/proc.h" +// #include "fs/fat32.h" // Decoupled +#include "lib/string.h" + +static Inode *global_root_inode = nullptr; + +static const char *skipelem(const char *path, char *name) +{ + const char *s; + int len; + + while (*path == '/') + path++; + if (*path == 0) + return nullptr; + + s = path; + while (*path != '/' && *path != 0) + path++; + + len = path - s; + if (len >= 128) + len = 127; + + memmove(name, s, len); + name[len] = 0; + + while (*path == '/') + path++; + return path; +} + +void Inode::getattr(struct kstat *st) +{ + st->dev = dev; + st->ino = inum; + st->type = type; + st->nlink = nlink; + st->size = size; + + st->uid = 0; + st->gid = 0; + st->mode = 0; +} + +namespace VFS +{ + // File System Registry + static FileSystem *filesystems[8]; + static int fs_count = 0; + + void register_fs(FileSystem *fs) + { + if (fs_count < 8) + { + filesystems[fs_count++] = fs; + } + } + + void init() + { + Drivers::uart_puts("[VFS] Inode subsystem initialized.\n"); + } + + void iput(Inode *ip) + { + if (ip == nullptr) + return; + + ip->lock.acquire(); + if(ip->ref_cnt < 1) + { + Drivers::uart_puts("panic: iput ref\n"); + while (1) + ; + } + ip->ref_cnt--; + int ref = ip->ref_cnt; + ip->lock.release(); + + if (ref == 0) + { + delete ip; + } + } + + Inode* idup(Inode *ip) + { + if (ip == nullptr) + return nullptr; + + ip->lock.acquire(); + ip->ref_cnt++; + ip->lock.release(); + return ip; + } + + void ilock(Inode *ip) + { + if (ip == 0 || ip->ref_cnt < 1) + { + Drivers::uart_puts("panic: ilock\n"); + while (1) + ; + } + + ip->lock.acquire(); + + } + + void iunlock(Inode *ip) + { + if (ip == 0 || !ip->lock.holding() || ip->ref_cnt < 1) + { + Drivers::uart_puts("panic: iunlock\n"); + while (1) + ; + } + ip->lock.release(); + } + + void iunlockput(Inode *ip) + { + if (!ip) + return; + iunlock(ip); + iput(ip); + } + + void mount_root(Inode *root) + { + if (global_root_inode) + { + Drivers::uart_puts("VFS: Root already mounted!\n"); + return; + } + global_root_inode = root; + Drivers::uart_puts("[VFS] Root filesystem mounted.\n"); + } + + Inode *get_root() + { + if (global_root_inode == nullptr) + { + // Try to mount the first registered FS + if (fs_count > 0) + { + Drivers::uart_puts("[VFS] Lazy init: Mounting root FS...\n"); + filesystems[0]->init(); + mount_root(filesystems[0]->root()); + } + else + { + Drivers::uart_puts("[VFS] No filesystem registered!\n"); + } + } + if (!global_root_inode) + return nullptr; + return idup(global_root_inode); + } + + Inode *namei(const char *path) + { + char name[128]; + Inode *ip, *next; + struct Proc *p = myproc(); + + // 1. 确定起点 + if (*path == '/') + { + ip = get_root(); + } + else + { + if (p->cwd == nullptr) + { + ip = get_root(); + } + else + { + ip = idup(p->cwd); + } + } + + if (ip == nullptr) + return nullptr; + + while ((path = skipelem(path, name)) != nullptr) + { + if (strcmp(name, ".") == 0) + { + continue; + } + + if (strcmp(name, "..") == 0) + { + Inode *root = get_root(); + bool is_root = (ip->inum == root->inum); + iput(root); + + if (is_root) + { + continue; + } + } + + ilock(ip); + + if (ip->type != T_DIR) + { + iunlockput(ip); + return nullptr; + } + + next = ip->lookup(name); + iunlockput(ip); + + ip = next; + if (ip == nullptr) + return nullptr; + } + + return ip; + } + + Inode *nameiparent(const char* path, char* name) + { + Inode* ip; + Inode* next; + + if (*path == '/') + ip = get_root(); + else + ip = idup(myproc()->cwd ? myproc()->cwd : get_root()); + + while ((path = skipelem(path, name)) != nullptr) + { + if (*path == 0) + { + return ip; + } + + ilock(ip); + if (ip->type != T_DIR) + { + iunlockput(ip); + return nullptr; + } + + next = ip->lookup(name); + iunlockput(ip); + + ip = next; + if (!ip) + return nullptr; + } + iput(ip); + return nullptr; + } +} // namespace VFS |
