From 9c65dba412e0cd94b11a6efd0244ce2065f58f7d Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 23 Oct 2023 22:47:49 +0200 Subject: [PATCH] kernel: Add a registry for file system implementations --- kernel/CMakeLists.txt | 3 +- kernel/src/fs/FSRegistry.cpp | 96 ++++++++++++++++++++++++++++++++++++ kernel/src/fs/FSRegistry.h | 62 +++++++++++++++++++++++ kernel/src/main.cpp | 2 + kernel/src/sys/mount.cpp | 19 +++---- 5 files changed, 172 insertions(+), 10 deletions(-) create mode 100644 kernel/src/fs/FSRegistry.cpp create mode 100644 kernel/src/fs/FSRegistry.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index d7ccf4fe..b9c3ca7a 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -57,6 +57,7 @@ set(SOURCES src/fs/GPT.cpp src/fs/StorageCache.cpp src/fs/OpenFileDescription.cpp + src/fs/FSRegistry.cpp src/net/UnixSocket.cpp src/fs/tmpfs/FileSystem.cpp src/fs/tmpfs/Inode.cpp @@ -119,7 +120,7 @@ target_link_libraries(moon luna-freestanding) target_compile_definitions(moon PRIVATE IN_MOON) target_compile_options(moon PRIVATE ${COMMON_FLAGS}) -target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel -ffreestanding) +target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel -ffreestanding -fno-threadsafe-statics) if("${LUNA_ARCH}" MATCHES "x86_64") target_compile_options(moon PRIVATE -mno-red-zone) diff --git a/kernel/src/fs/FSRegistry.cpp b/kernel/src/fs/FSRegistry.cpp new file mode 100644 index 00000000..97f5aad4 --- /dev/null +++ b/kernel/src/fs/FSRegistry.cpp @@ -0,0 +1,96 @@ +/** + * @file FSRegistry.cpp + * @author apio (cloudapio.eu) + * @brief Kernel registry of available file system implementations. + * + * @copyright Copyright (c) 2023, the Luna authors. + * + */ + +#include "fs/FSRegistry.h" +#include "fs/devpts/FileSystem.h" +#include "fs/ext2/FileSystem.h" +#include "fs/tmpfs/FileSystem.h" +#include "lib/Mutex.h" + +struct VirtualFileSystemDescriptor +{ + StringView name; + VirtualFileSystemFactoryFunction factory_function; +}; + +struct PhysicalFileSystemDescriptor +{ + StringView name; + PhysicalFileSystemFactoryFunction factory_function; +}; + +Vector g_virtual_filesystems; +Vector g_physical_filesystems; + +static Mutex g_lock; + +namespace FSRegistry +{ + Result init() + { + TRY(register_virtual_filesystem(TmpFS::FileSystem::create, "tmpfs")); + TRY(register_virtual_filesystem(DevPTS::FileSystem::create, "devpts")); + TRY(register_virtual_filesystem(DeviceRegistry::create_devfs_instance, "devfs")); + TRY(register_physical_filesystem(Ext2::FileSystem::create, "ext2")); + + return {}; + } + + Result register_virtual_filesystem(VirtualFileSystemFactoryFunction factory_function, StringView name) + { + ScopedMutexLock lock(g_lock); + + for (const auto& descriptor : g_virtual_filesystems) + { + if (descriptor.name == name) return err(EEXIST); + } + + auto descriptor = VirtualFileSystemDescriptor { .name = name, .factory_function = factory_function }; + + return g_virtual_filesystems.try_append(move(descriptor)); + } + + Result register_physical_filesystem(PhysicalFileSystemFactoryFunction factory_function, StringView name) + { + ScopedMutexLock lock(g_lock); + + for (const auto& descriptor : g_physical_filesystems) + { + if (descriptor.name == name) return err(EEXIST); + } + + auto descriptor = PhysicalFileSystemDescriptor { .name = name, .factory_function = factory_function }; + + return g_physical_filesystems.try_append(move(descriptor)); + } + + Result lookup_virtual_filesystem(StringView name) + { + ScopedMutexLock lock(g_lock); + + for (const auto& descriptor : g_virtual_filesystems) + { + if (descriptor.name == name) return descriptor.factory_function; + } + + return err(ENODEV); + } + + Result lookup_physical_filesystem(StringView name) + { + ScopedMutexLock lock(g_lock); + + for (const auto& descriptor : g_physical_filesystems) + { + if (descriptor.name == name) return descriptor.factory_function; + } + + return err(ENODEV); + } +} diff --git a/kernel/src/fs/FSRegistry.h b/kernel/src/fs/FSRegistry.h new file mode 100644 index 00000000..88df7b9b --- /dev/null +++ b/kernel/src/fs/FSRegistry.h @@ -0,0 +1,62 @@ +/** + * @file FSRegistry.h + * @author apio (cloudapio.eu) + * @brief Kernel registry of available file system implementations. + * + * @copyright Copyright (c) 2023, the Luna authors. + * + */ + +#pragma once +#include "fs/VFS.h" +#include "fs/devices/Device.h" + +typedef Result> (*VirtualFileSystemFactoryFunction)(void); +typedef Result> (*PhysicalFileSystemFactoryFunction)(SharedPtr); + +namespace FSRegistry +{ + /** + * @brief Register the built-in file system implementations. + * + * @return Result Whether the operation succeeded. + */ + Result init(); + + /** + * @brief Register a "virtual" (in-memory) file system implementation, associating a name to it. + * + * @param factory_function The factory function to use to create new instances of this file system. + * @param name The name to associate with this file system implementation. + * @return Result Whether the operation succeeded. + */ + Result register_virtual_filesystem(VirtualFileSystemFactoryFunction factory_function, StringView name); + + /** + * @brief Register a "physical" (mounted from a device) file system implementation, associating a name + * to it. + * + * @param factory_function The factory function to use to create new instances of this file system. + * @param name The name to associate with this file system implementation. + * @return Result Whether the operation succeeded. + */ + Result register_physical_filesystem(PhysicalFileSystemFactoryFunction factory_function, StringView name); + + /** + * @brief Find a "virtual" (in-memory) file system implementation by name. + * + * @param name The name to look for. + * @return Result An error, or the factory function to create file systems of this + * type. + */ + Result lookup_virtual_filesystem(StringView name); + + /** + * @brief Find a "physical" (mounted from a device) file system implementation by name. + * + * @param name The name to look for. + * @return Result An error, or the factory function to create file systems of + * this type. + */ + Result lookup_physical_filesystem(StringView name); +} diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 49245b12..3edecb66 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,6 +5,7 @@ #include "binfmt/BinaryFormat.h" #include "boot/Init.h" #include "config.h" +#include "fs/FSRegistry.h" #include "fs/InitRD.h" #include "fs/devices/DeviceRegistry.h" #include "fs/devices/PTYMultiplexer.h" @@ -62,6 +63,7 @@ void oom_thread() mark_critical(DeviceRegistry::init(), "Failed to register initial devices"); mark_critical(BinaryFormat::init(), "Failed to register initial binary formats"); + mark_critical(FSRegistry::init(), "Failed to register initial file systems"); auto init = mark_critical(VFS::resolve_path("/bin/preinit", Credentials {}), "Can't find init in the initial ramfs!"); diff --git a/kernel/src/sys/mount.cpp b/kernel/src/sys/mount.cpp index 20b4a580..84a6ba39 100644 --- a/kernel/src/sys/mount.cpp +++ b/kernel/src/sys/mount.cpp @@ -1,4 +1,5 @@ #include "Pledge.h" +#include "fs/FSRegistry.h" #include "fs/VFS.h" #include "fs/devpts/FileSystem.h" #include "fs/ext2/FileSystem.h" @@ -26,18 +27,18 @@ Result sys_mount(Registers*, SyscallArgs args) SharedPtr fs; - if (fstype.view() == "tmpfs") fs = TRY(TmpFS::FileSystem::create()); - else if (fstype.view() == "devpts") - fs = TRY(DevPTS::FileSystem::create()); - else if (fstype.view() == "devfs") - fs = TRY(DeviceRegistry::create_devfs_instance()); - else if (fstype.view() == "ext2") + auto maybe_virtual = FSRegistry::lookup_virtual_filesystem(fstype.view()); + if (maybe_virtual.has_value()) { - auto source_device = TRY(get_source()); - fs = TRY(Ext2::FileSystem::create(source_device)); + auto factory = maybe_virtual.release_value(); + fs = TRY(factory()); } else - return err(ENODEV); + { + auto factory = TRY(FSRegistry::lookup_physical_filesystem(fstype.view())); + auto device = TRY(get_source()); + fs = TRY(factory(device)); + } TRY(VFS::mount(target.chars(), fs, current->auth, current->current_directory));