Compare commits

...

4 Commits

Author SHA1 Message Date
cea1b030ff
kernel: Add locking to BinaryFormat and DeviceRegistry
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-23 22:48:04 +02:00
9c65dba412
kernel: Add a registry for file system implementations 2023-10-23 22:47:49 +02:00
ba4e807f8e
kernel: Fix off-by-one error in symbol lookup and add locking
This resulted in very weird backtraces.
2023-10-23 22:47:20 +02:00
b3cbbea9d6
kernel: Move file descriptors into their own separate file 2023-10-23 20:13:11 +02:00
12 changed files with 265 additions and 80 deletions

View File

@ -56,6 +56,8 @@ set(SOURCES
src/fs/MBR.cpp
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
@ -118,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)

View File

@ -3,6 +3,7 @@
#include "arch/MMU.h"
#include "boot/bootboot.h"
#include "fs/InitRD.h"
#include "lib/Mutex.h"
#include <luna/Scanf.h>
#include <luna/TarStream.h>
#include <luna/Vector.h>
@ -18,6 +19,7 @@ struct Symbol
};
Vector<Symbol> g_symbols;
static Mutex g_lock;
extern const u8 kernel_start;
extern const u8 kernel_end;
@ -38,6 +40,8 @@ namespace Symbols
{
Result<void> load()
{
ScopedMutexLock lock(g_lock);
const u64 virtual_initrd_address = MMU::translate_physical_address(bootboot.initrd_ptr);
TarStream stream;
@ -80,14 +84,11 @@ namespace Symbols
if (address < (u64)&kernel_start) return StringView {};
if (address >= (u64)&kernel_end) return StringView {};
ScopedMutexLock lock(g_lock);
for (isize i = (isize)g_symbols.size() - 1; i >= 0; i--)
{
if (g_symbols[i].address < address)
{
usize index = i + 1;
if (index == g_symbols.size()) return StringView {};
return StringView { g_symbols[index].symbol };
}
if (g_symbols[i].address < address) { return StringView { g_symbols[i].symbol }; }
}
return StringView {};

View File

@ -1,6 +1,7 @@
#include "binfmt/BinaryFormat.h"
#include "binfmt/ELF.h"
#include "binfmt/Script.h"
#include "lib/Mutex.h"
struct BinaryFormatDescriptor
{
@ -10,6 +11,8 @@ struct BinaryFormatDescriptor
Vector<BinaryFormatDescriptor> g_binary_formats;
static Mutex g_lock;
Result<void> BinaryFormat::init()
{
TRY(register_binary_format(ELFLoader::create, nullptr));
@ -20,6 +23,7 @@ Result<void> BinaryFormat::init()
Result<void> BinaryFormat::register_binary_format(binfmt_loader_creator_t creator, void* arg)
{
ScopedMutexLock lock(g_lock);
return g_binary_formats.try_append({ creator, arg });
}
@ -27,6 +31,8 @@ Result<SharedPtr<BinaryFormatLoader>> BinaryFormat::create_loader(SharedPtr<VFS:
{
if (recursion_level >= 8) return err(ELOOP);
ScopedMutexLock lock(g_lock);
for (const auto& format : g_binary_formats)
{
auto loader = TRY(format.creator(inode, format.arg, recursion_level));

View File

@ -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<VirtualFileSystemDescriptor> g_virtual_filesystems;
Vector<PhysicalFileSystemDescriptor> g_physical_filesystems;
static Mutex g_lock;
namespace FSRegistry
{
Result<void> 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<void> 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<void> 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<VirtualFileSystemFactoryFunction> 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<PhysicalFileSystemFactoryFunction> 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);
}
}

View File

@ -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<SharedPtr<VFS::FileSystem>> (*VirtualFileSystemFactoryFunction)(void);
typedef Result<SharedPtr<VFS::FileSystem>> (*PhysicalFileSystemFactoryFunction)(SharedPtr<Device>);
namespace FSRegistry
{
/**
* @brief Register the built-in file system implementations.
*
* @return Result<void> Whether the operation succeeded.
*/
Result<void> 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<void> Whether the operation succeeded.
*/
Result<void> 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<void> Whether the operation succeeded.
*/
Result<void> 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<VirtualFileSystemFactoryFunction> An error, or the factory function to create file systems of this
* type.
*/
Result<VirtualFileSystemFactoryFunction> 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<PhysicalFileSystemFactoryFunction> An error, or the factory function to create file systems of
* this type.
*/
Result<PhysicalFileSystemFactoryFunction> lookup_physical_filesystem(StringView name);
}

View File

@ -0,0 +1,33 @@
#include "fs/OpenFileDescription.h"
#include <bits/open-flags.h>
OpenFileDescription::OpenFileDescription(SharedPtr<VFS::Inode> ino, int fl) : inode(ino), flags(fl)
{
inode->add_handle();
}
OpenFileDescription::~OpenFileDescription()
{
inode->remove_handle();
inode->did_close();
}
bool FileDescriptor::should_append()
{
return description->flags & O_APPEND;
}
bool FileDescriptor::should_block()
{
return !(description->flags & O_NONBLOCK);
}
bool FileDescriptor::is_readable()
{
return description->flags & O_RDONLY;
}
bool FileDescriptor::is_writable()
{
return description->flags & O_WRONLY;
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "fs/VFS.h"
#include <luna/SharedPtr.h>
#include <luna/String.h>
struct OpenFileDescription : public Shareable
{
SharedPtr<VFS::Inode> inode;
int flags { 0 };
String path;
OpenFileDescription(SharedPtr<VFS::Inode>, int);
~OpenFileDescription();
};
struct FileDescriptor
{
SharedPtr<OpenFileDescription> description;
usize offset { 0 };
int flags { 0 };
bool should_append();
bool should_block();
bool is_writable();
bool is_readable();
SharedPtr<VFS::Inode> inode()
{
return description->inode;
}
int& status_flags()
{
return description->flags;
}
};

View File

@ -12,6 +12,7 @@
#include "fs/devices/UARTDevice.h"
#include "fs/devices/ZeroDevice.h"
#include "fs/tmpfs/FileSystem.h"
#include "lib/Mutex.h"
#include "thread/Thread.h"
#include <luna/Vector.h>
@ -26,10 +27,14 @@ struct DeviceDescriptor
Vector<DeviceDescriptor> g_available_devices = {};
static Mutex g_lock;
namespace DeviceRegistry
{
Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor)
{
ScopedMutexLock lock(g_lock);
for (const auto& descriptor : g_available_devices)
{
if (descriptor.major == major && descriptor.minor == minor) return descriptor.device;
@ -38,7 +43,7 @@ namespace DeviceRegistry
return err(ENODEV);
}
Result<void> create_special_device_inode(SharedPtr<VFS::FileSystem> fs, const DeviceDescriptor& descriptor)
static Result<void> create_special_device_inode(SharedPtr<VFS::FileSystem> fs, const DeviceDescriptor& descriptor)
{
auto inode = TRY(fs->create_device_inode(descriptor.major, descriptor.minor, descriptor.mode));
TRY(fs->root_inode()->add_entry(inode, descriptor.name));
@ -48,6 +53,8 @@ namespace DeviceRegistry
Result<void> register_special_device(u32 major, u32 minor, SharedPtr<Device> device, mode_t mode)
{
ScopedMutexLock lock(g_lock);
for (const auto& descriptor : g_available_devices)
{
if (descriptor.major == major && descriptor.minor == minor) return err(EEXIST);
@ -82,7 +89,7 @@ namespace DeviceRegistry
dev_t next_null_device_id()
{
static u32 next_minor = 0;
static Atomic<u32> next_minor = 0;
return luna_dev_makedev(0, next_minor++);
}

View File

@ -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!");

View File

@ -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<u64> sys_mount(Registers*, SyscallArgs args)
SharedPtr<VFS::FileSystem> 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));

View File

@ -236,34 +236,3 @@ void Thread::send_signal(int signo)
wake_up();
}
}
OpenFileDescription::OpenFileDescription(SharedPtr<VFS::Inode> ino, int fl) : inode(ino), flags(fl)
{
inode->add_handle();
}
OpenFileDescription::~OpenFileDescription()
{
inode->remove_handle();
inode->did_close();
}
bool FileDescriptor::should_append()
{
return description->flags & O_APPEND;
}
bool FileDescriptor::should_block()
{
return !(description->flags & O_NONBLOCK);
}
bool FileDescriptor::is_readable()
{
return description->flags & O_RDONLY;
}
bool FileDescriptor::is_writable()
{
return description->flags & O_WRONLY;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "arch/MMU.h"
#include "fs/OpenFileDescription.h"
#include "fs/VFS.h"
#include "memory/AddressSpace.h"
#include <bits/signal.h>
@ -29,37 +30,6 @@ enum class ThreadState
Dying
};
struct OpenFileDescription : public Shareable
{
SharedPtr<VFS::Inode> inode;
int flags { 0 };
OpenFileDescription(SharedPtr<VFS::Inode>, int);
~OpenFileDescription();
};
struct FileDescriptor
{
SharedPtr<OpenFileDescription> description;
usize offset { 0 };
int flags { 0 };
bool should_append();
bool should_block();
bool is_writable();
bool is_readable();
SharedPtr<VFS::Inode> inode()
{
return description->inode;
}
int& status_flags()
{
return description->flags;
}
};
static constexpr int FD_MAX = 64;
struct Credentials