// 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