diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 274f7021..85bb4f3b 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -32,6 +32,7 @@ set(KERNEL_SOURCES kernel/FS/DevFS/FileSystem.cpp kernel/FS/Ext2/FileSystem.cpp kernel/FS/Ext2/Inode.cpp + kernel/FS/FileSystem.cpp kernel/FS/Inode.cpp kernel/FS/Pipe.cpp kernel/FS/ProcFS/FileSystem.cpp diff --git a/kernel/include/kernel/FS/Ext2/FileSystem.h b/kernel/include/kernel/FS/Ext2/FileSystem.h index 8949aaf3..cf0bbc27 100644 --- a/kernel/include/kernel/FS/Ext2/FileSystem.h +++ b/kernel/include/kernel/FS/Ext2/FileSystem.h @@ -45,7 +45,8 @@ namespace Kernel }; public: - static BAN::ErrorOr create(BAN::RefPtr); + static BAN::ErrorOr probe(BAN::RefPtr); + static BAN::ErrorOr> create(BAN::RefPtr); virtual BAN::RefPtr root_inode() override { return m_root_inode; } @@ -120,6 +121,7 @@ namespace Kernel Ext2::Superblock m_superblock; friend class Ext2Inode; + friend class BAN::RefPtr; }; } diff --git a/kernel/include/kernel/FS/FileSystem.h b/kernel/include/kernel/FS/FileSystem.h index 35798e51..6a3cef0a 100644 --- a/kernel/include/kernel/FS/FileSystem.h +++ b/kernel/include/kernel/FS/FileSystem.h @@ -1,14 +1,18 @@ #pragma once +#include #include namespace Kernel { - class FileSystem + class FileSystem : public BAN::RefCounted { public: virtual ~FileSystem() {} + + static BAN::ErrorOr> from_block_device(BAN::RefPtr); + virtual BAN::RefPtr root_inode() = 0; virtual dev_t dev() const = 0; diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 1b56bf32..3cd40875 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -13,7 +13,6 @@ namespace Kernel public: static void initialize(BAN::StringView); static VirtualFileSystem& get(); - virtual ~VirtualFileSystem() {}; virtual BAN::RefPtr root_inode() override { return m_root_fs->root_inode(); } @@ -21,7 +20,7 @@ namespace Kernel virtual dev_t dev() const override { return 0; } BAN::ErrorOr mount(const Credentials&, BAN::StringView, BAN::StringView); - BAN::ErrorOr mount(const Credentials&, FileSystem*, BAN::StringView); + BAN::ErrorOr mount(const Credentials&, BAN::RefPtr, BAN::StringView); struct File { @@ -35,16 +34,18 @@ namespace Kernel struct MountPoint { + BAN::RefPtr target; File host; - FileSystem* target; }; MountPoint* mount_from_host_inode(BAN::RefPtr); MountPoint* mount_from_root_inode(BAN::RefPtr); private: Mutex m_mutex; - FileSystem* m_root_fs = nullptr; + BAN::RefPtr m_root_fs; BAN::Vector m_mount_points; + + friend class BAN::RefPtr; }; } diff --git a/kernel/kernel/FS/Ext2/FileSystem.cpp b/kernel/kernel/FS/Ext2/FileSystem.cpp index 0b3c91a0..c19d21e0 100644 --- a/kernel/kernel/FS/Ext2/FileSystem.cpp +++ b/kernel/kernel/FS/Ext2/FileSystem.cpp @@ -9,15 +9,34 @@ namespace Kernel { - BAN::ErrorOr Ext2FS::create(BAN::RefPtr block_device) + BAN::ErrorOr Ext2FS::probe(BAN::RefPtr block_device) { - Ext2FS* ext2fs = new Ext2FS(block_device); - if (ext2fs == nullptr) - return BAN::Error::from_errno(ENOMEM); - BAN::ScopeGuard guard([ext2fs] { delete ext2fs; }); + Ext2::Superblock superblock; + + // Read superblock from disk + { + const uint32_t sector_size = block_device->blksize(); + ASSERT(1024 % sector_size == 0); + + const uint32_t lba = 1024 / sector_size; + const uint32_t sector_count = BAN::Math::div_round_up(sizeof(Ext2::Superblock), sector_size); + + BAN::Vector superblock_buffer; + TRY(superblock_buffer.resize(sector_count * sector_size)); + + TRY(block_device->read_blocks(lba, sector_count, BAN::ByteSpan(superblock_buffer.span()))); + + memcpy(&superblock, superblock_buffer.data(), sizeof(Ext2::Superblock)); + } + + return superblock.magic == Ext2::Enum::SUPER_MAGIC; + } + + BAN::ErrorOr> Ext2FS::create(BAN::RefPtr block_device) + { + auto ext2fs = TRY(BAN::RefPtr::create(block_device)); TRY(ext2fs->initialize_superblock()); TRY(ext2fs->initialize_root_inode()); - guard.disable(); return ext2fs; } diff --git a/kernel/kernel/FS/FileSystem.cpp b/kernel/kernel/FS/FileSystem.cpp new file mode 100644 index 00000000..2c6967c8 --- /dev/null +++ b/kernel/kernel/FS/FileSystem.cpp @@ -0,0 +1,15 @@ +#include +#include + +namespace Kernel +{ + + BAN::ErrorOr> FileSystem::from_block_device(BAN::RefPtr block_device) + { + if (auto res = Ext2FS::probe(block_device); !res.is_error() && res.value()) + return BAN::RefPtr(TRY(Ext2FS::create(block_device))); + dprintln("Unsupported filesystem"); + return BAN::Error::from_errno(ENOTSUP); + } + +} diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index cf1a66ea..84f88ef5 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -11,13 +10,12 @@ namespace Kernel { - static VirtualFileSystem* s_instance = nullptr; + static BAN::RefPtr s_instance; void VirtualFileSystem::initialize(BAN::StringView root) { - ASSERT(s_instance == nullptr); - s_instance = new VirtualFileSystem(); - ASSERT(s_instance); + ASSERT(!s_instance); + s_instance = MUST(BAN::RefPtr::create()); ASSERT(root.size() >= 5 && root.substring(0, 5) == "/dev/"sv);; root = root.substring(5); @@ -25,14 +23,14 @@ namespace Kernel auto partition_inode = MUST(DevFileSystem::get().root_inode()->find_inode(root)); if (!partition_inode->is_device() || !static_cast(partition_inode.ptr())->is_partition()) Kernel::panic("Specified root '/dev/{}' does not name a partition", root); - s_instance->m_root_fs = MUST(Ext2FS::create(static_cast(partition_inode.ptr()))); + s_instance->m_root_fs = MUST(FileSystem::from_block_device(static_cast(partition_inode.ptr()))); Credentials root_creds { 0, 0, 0, 0 }; MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"sv)); MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"sv)); - auto* tmpfs = MUST(TmpFileSystem::create(1024, 0777, 0, 0)); + auto tmpfs = MUST(TmpFileSystem::create(1024, 0777, 0, 0)); MUST(s_instance->mount(root_creds, tmpfs, "/tmp"sv)); } @@ -52,19 +50,18 @@ namespace Kernel if (!device->mode().ifblk()) return BAN::Error::from_errno(ENOTBLK); - auto* block_device = static_cast(device); - auto* file_system = TRY(Ext2FS::create(block_device)); + auto file_system = TRY(FileSystem::from_block_device(static_cast(device))); return mount(credentials, file_system, target); } - BAN::ErrorOr VirtualFileSystem::mount(const Credentials& credentials, FileSystem* file_system, BAN::StringView path) + BAN::ErrorOr VirtualFileSystem::mount(const Credentials& credentials, BAN::RefPtr file_system, BAN::StringView path) { auto file = TRY(file_from_absolute_path(credentials, path, true)); if (!file.inode->mode().ifdir()) return BAN::Error::from_errno(ENOTDIR); LockGuard _(m_mutex); - TRY(m_mount_points.push_back({ file, file_system })); + TRY(m_mount_points.push_back({ file_system, file })); return {}; }