From 3315d797423fe079f1f3c6c10f499e5d32ea2b44 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Tue, 8 Apr 2025 05:04:04 +0000 Subject: [PATCH] fix(kernel/vfs): support multiple roots --- Kernel/include/filesystem.hpp | 2 +- Kernel/include/filesystem/ramfs.hpp | 3 ++- Kernel/include/subsystems.hpp | 31 +++++++++++++++++++++++++++++ Kernel/kernel_thread.cpp | 16 +++++++++------ Kernel/storage/cache.cpp | 7 ++++--- Kernel/storage/filesystem.cpp | 28 +++++++++++++++++++------- Kernel/storage/fs/ramfs.cpp | 28 +++++++++++--------------- Kernel/subsystem/linux/init.cpp | 20 +++++++++++++++++++ Kernel/subsystem/windows/init.cpp | 14 +++++++++++++ Kernel/tasking/thread.cpp | 8 +++----- 10 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 Kernel/include/subsystems.hpp diff --git a/Kernel/include/filesystem.hpp b/Kernel/include/filesystem.hpp index 2bbdf690..bda0be7d 100644 --- a/Kernel/include/filesystem.hpp +++ b/Kernel/include/filesystem.hpp @@ -132,7 +132,7 @@ namespace vfs FileNode *CacheSearchReturnLast(FileNode *Parent, const char **Path); FileNode *CacheRecursiveSearch(FileNode *Root, const char *NameOrPath, bool IsName); - FileNode *CacheLookup(const char *Path); + FileNode *CacheLookup(FileNode *Parent, const char *Path); FileNode *CreateCacheNode(FileNode *Parent, Inode *Node, const char *Name, mode_t Mode); int RemoveCacheNode(FileNode *Node); diff --git a/Kernel/include/filesystem/ramfs.hpp b/Kernel/include/filesystem/ramfs.hpp index 5304352f..bd39df3a 100644 --- a/Kernel/include/filesystem/ramfs.hpp +++ b/Kernel/include/filesystem/ramfs.hpp @@ -131,6 +131,7 @@ namespace vfs public: dev_t DeviceID = -1; ino_t NextInode = 0; + std::string RootName; int Lookup(struct Inode *Parent, const char *Name, struct Inode **Result); int Create(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result); @@ -146,4 +147,4 @@ namespace vfs }; } -bool MountRAMFS(Inode *Parent, const char *Name, size_t Index); +bool MountRAMFS(FileNode *Parent, const char *Name, size_t Index); diff --git a/Kernel/include/subsystems.hpp b/Kernel/include/subsystems.hpp new file mode 100644 index 00000000..4119e4ff --- /dev/null +++ b/Kernel/include/subsystems.hpp @@ -0,0 +1,31 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +namespace Subsystem +{ + namespace Linux + { + void InitializeSubSystem(); + } + + namespace Windows + { + void InitializeSubSystem(); + } +} diff --git a/Kernel/kernel_thread.cpp b/Kernel/kernel_thread.cpp index 6bbc16f9..9f0f81c4 100644 --- a/Kernel/kernel_thread.cpp +++ b/Kernel/kernel_thread.cpp @@ -21,6 +21,7 @@ #endif #include +#include #include #include #include @@ -69,12 +70,13 @@ int SpawnLinuxInit() "/startup/init"}; const char *foundPath = nullptr; + FileNode *root = fs->GetRoot(1); for (const std::string &path : fallbackPaths) { - if (!fs->PathExists(path.c_str(), fs->GetRoot(1))) + const char *str = path.c_str(); + if (!fs->PathExists(str, root)) continue; - - foundPath = path.c_str(); + foundPath = str; break; } @@ -135,6 +137,10 @@ void KernelMainThread() // ->Rename("Kernel Shell"); #endif + KPrint("Loading Subsystems"); + Subsystem::Linux::InitializeSubSystem(); + Subsystem::Windows::InitializeSubSystem(); + KPrint("Executing %s", Config.InitPath); int ExitCode = -1; Tasking::PCB *initProc; @@ -164,9 +170,7 @@ Exit: KPrint("Dropping to kernel shell"); TaskManager->Sleep(1000); - TaskManager->CreateThread(thisProcess, - Tasking::IP(KShellThread)) - ->Rename("Kernel Shell"); + TaskManager->CreateThread(thisProcess, Tasking::IP(KShellThread))->Rename("Kernel Shell"); CPU::Halt(true); } diff --git a/Kernel/storage/cache.cpp b/Kernel/storage/cache.cpp index 12932a0f..bc801785 100644 --- a/Kernel/storage/cache.cpp +++ b/Kernel/storage/cache.cpp @@ -175,12 +175,13 @@ namespace vfs return nullptr; } - FileNode *Virtual::CacheLookup(const char *Path) + FileNode *Virtual::CacheLookup(FileNode *Parent, const char *Path) { debug("Cache lookup for \"%s\"", Path); - FileNode *rootNode = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0); + if (Parent == nullptr) + Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0); - FileNode *ret = CacheRecursiveSearch(rootNode, Path, false); + FileNode *ret = CacheRecursiveSearch(Parent, Path, false); if (ret) return ret; diff --git a/Kernel/storage/filesystem.cpp b/Kernel/storage/filesystem.cpp index 766b2596..5f9fa19e 100644 --- a/Kernel/storage/filesystem.cpp +++ b/Kernel/storage/filesystem.cpp @@ -137,14 +137,22 @@ namespace vfs { char *path = strdup(Path); char *lastSlash = strrchr(path, '/'); - if (lastSlash == path) - lastSlash++; - *lastSlash = '\0'; + if (lastSlash) + { + if (lastSlash == path) + lastSlash++; + *lastSlash = '\0'; + } FileNode *parentNode = this->GetByPath(path, Parent); + if (parentNode == nullptr && Parent != nullptr) + parentNode = Parent; free(path); lastSlash = strrchr(Path, '/'); - lastSlash++; + if (lastSlash) + lastSlash++; + else + lastSlash = (char *)Path; return this->CreateCacheNode(parentNode, Node, lastSlash, Node->Mode); } @@ -160,8 +168,13 @@ namespace vfs FileNode *Virtual::GetByPath(const char *Path, FileNode *Parent) { debug("GetByPath: %s", Path); - if (Parent == nullptr || this->PathIsAbsolute(Path)) - Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0); + if (Parent == nullptr) + { + if (fs->PathIsRelative(Path)) + Parent = thisProcess ? thisProcess->CWD : thisProcess->Info.RootNode; + else + Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0); + } if (strcmp(Path, ".") == 0) return Parent; @@ -214,6 +227,7 @@ namespace vfs auto it = DeviceMap.find(__Parent->Node->Device); if (unlikely(it == DeviceMap.end())) ReturnLogError(nullptr, "Device %d not found", __Parent->Node->Device); + debug("found fs %s", it->second.fsi->Name); if (it->second.fsi->Ops.Lookup == NULL) ReturnLogError(nullptr, "Lookup not supported for %d", it->first); @@ -321,7 +335,7 @@ namespace vfs bool Virtual::PathExists(const char *Path, FileNode *Parent) { - FileNode *fn = this->CacheLookup(Path); + FileNode *fn = this->CacheLookup(Parent, Path); if (fn) return true; diff --git a/Kernel/storage/fs/ramfs.cpp b/Kernel/storage/fs/ramfs.cpp index ef822cea..56a9ff8d 100644 --- a/Kernel/storage/fs/ramfs.cpp +++ b/Kernel/storage/fs/ramfs.cpp @@ -33,7 +33,7 @@ namespace vfs cwk_path_get_basename(Name, &basename, &length); if (basename == NULL) { - if (strcmp(Name, "/") == 0) + if (strcmp(Name, RootName.c_str()) == 0) { auto &it = Files.at(0); *Result = &it->Node; @@ -90,6 +90,7 @@ namespace vfs RAMFSInode *node = new RAMFSInode; node->Name.assign(basename, length); node->Mode = Mode; + node->Node = inode; auto file = Files.insert(std::make_pair(NextInode, node)); assert(file.second == true); @@ -383,25 +384,15 @@ O2 int __ramfs_Destroy(FileSystemInfo *fsi) return 0; } -bool MountRAMFS(Inode *Parent, const char *Name, size_t Index) +bool MountRAMFS(FileNode *Parent, const char *Name, size_t Index) { vfs::RAMFS *ramfs = new vfs::RAMFS; ramfs->DeviceID = fs->EarlyReserveDevice(); - - if (Parent == nullptr) - { - ramfs->Create(nullptr, Name, S_IFDIR | 0755, &Parent); - if (Parent == nullptr) - { - error("Failed to create root inode"); - delete ramfs; - return false; - } - } + ramfs->RootName.assign(Name); FileSystemInfo *fsi = new FileSystemInfo; fsi->Name = "ramfs"; - fsi->RootName = "/"; + fsi->RootName = Name; fsi->Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP; fsi->SuperOps.DeleteInode = __ramfs_DestroyInode; fsi->SuperOps.Destroy = __ramfs_Destroy; @@ -415,7 +406,12 @@ bool MountRAMFS(Inode *Parent, const char *Name, size_t Index) fsi->Ops.Stat = __ramfs_Stat; fsi->PrivateData = ramfs; - fs->LateRegisterFileSystem(ramfs->DeviceID, fsi, Parent); - fs->AddRootAt(Parent, Index); + Inode *root = nullptr; + ramfs->Create(nullptr, Name, S_IFDIR | 0755, &root); + + fs->LateRegisterFileSystem(ramfs->DeviceID, fsi, root); + fs->AddRootAt(root, Index); + + fs->Mount(Parent, root, Name); return true; } diff --git a/Kernel/subsystem/linux/init.cpp b/Kernel/subsystem/linux/init.cpp index c2750856..e304d591 100644 --- a/Kernel/subsystem/linux/init.cpp +++ b/Kernel/subsystem/linux/init.cpp @@ -15,6 +15,8 @@ along with Fennix Kernel. If not, see . */ +#include + #include "../../kernel.h" namespace Subsystem::Linux @@ -23,5 +25,23 @@ namespace Subsystem::Linux void InitializeSubSystem() { + if (fs->RootExists(1) == false) + { + FileNode *nmnt = fs->GetByPath("/mnt", fs->GetRoot(0)); + assert(MountRAMFS(nmnt, "linux", 1)); + FileNode *linux = fs->GetRoot(1); + + FileNode *bin = fs->ForceCreate(linux, "bin", 0755); + FileNode *boot = fs->ForceCreate(linux, "boot", 0755); + FileNode *dev = fs->ForceCreate(linux, "dev", 0755); + FileNode *etc = fs->ForceCreate(linux, "etc", 0755); + FileNode *home = fs->ForceCreate(linux, "home", 0755); + FileNode *lib = fs->ForceCreate(linux, "lib", 0755); + FileNode *lib64 = fs->ForceCreate(linux, "lib64", 0755); + FileNode *media = fs->ForceCreate(linux, "media", 0755); + FileNode *mnt = fs->ForceCreate(linux, "mnt", 0755); + FileNode *opt = fs->ForceCreate(linux, "opt", 0755); + FileNode *proc = fs->ForceCreate(linux, "proc", 0755); + } } } diff --git a/Kernel/subsystem/windows/init.cpp b/Kernel/subsystem/windows/init.cpp index d6f071c2..a3f9dcf6 100644 --- a/Kernel/subsystem/windows/init.cpp +++ b/Kernel/subsystem/windows/init.cpp @@ -15,6 +15,8 @@ along with Fennix Kernel. If not, see . */ +#include + #include "../../kernel.h" namespace Subsystem::Windows @@ -23,5 +25,17 @@ namespace Subsystem::Windows void InitializeSubSystem() { + if (fs->RootExists(2) == false) + { + FileNode *nmnt = fs->GetByPath("/mnt", fs->GetRoot(0)); + assert(MountRAMFS(nmnt, "windows", 2)); + FileNode *win = fs->GetRoot(2); + + FileNode *windows = fs->ForceCreate(win, "Windows", 0755); + FileNode *programFiles = fs->ForceCreate(windows, "Program Files", 0755); + FileNode *programFilesX86 = fs->ForceCreate(windows, "Program Files (x86)", 0755); + FileNode *programData = fs->ForceCreate(windows, "ProgramData", 0755); + FileNode *users = fs->ForceCreate(windows, "Users", 0755); + } } } diff --git a/Kernel/tasking/thread.cpp b/Kernel/tasking/thread.cpp index cb1332fc..ed29bdf9 100644 --- a/Kernel/tasking/thread.cpp +++ b/Kernel/tasking/thread.cpp @@ -588,20 +588,18 @@ namespace Tasking switch (Compatibility) { case TaskCompatibility::Native: - // this->Info.RootNode = fs->FileSystemRoots->GetChildren()[0]; + this->Info.RootNode = fs->GetRoot(0); break; case TaskCompatibility::Linux: - // this->Info.RootNode = fs->FileSystemRoots->GetChildren()[1]; + this->Info.RootNode = fs->GetRoot(1); break; case TaskCompatibility::Windows: - // this->Info.RootNode = fs->FileSystemRoots->GetChildren()[2]; + this->Info.RootNode = fs->GetRoot(2); break; default: assert(!"Invalid compatibility mode"); break; } - /* FIXME */ - this->Info.RootNode = fs->GetRoot(0); if (this->Parent->Threads.size() == 0) {