From 06ce1f0667bbbade6db47139f932a28fe6fd1207 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 29 Mar 2023 21:34:48 +0300 Subject: [PATCH] Kernel: Rewrite mounting code --- kernel/Makefile | 1 - kernel/include/kernel/Device.h | 45 ++++++++-------- kernel/include/kernel/FS/Ext2.h | 13 ++--- kernel/include/kernel/FS/Inode.h | 28 ++++------ kernel/include/kernel/FS/VirtualFileSystem.h | 4 +- kernel/include/kernel/Input/PS2Controller.h | 19 +++++++ kernel/include/kernel/Input/PS2Keyboard.h | 33 ++++-------- kernel/kernel/Device.cpp | 4 +- kernel/kernel/FS/Ext2.cpp | 21 ++------ kernel/kernel/FS/Inode.cpp | 26 ---------- kernel/kernel/FS/VirtualFileSystem.cpp | 54 +++++++++++++------- kernel/kernel/Input/PS2Controller.cpp | 11 +++- kernel/kernel/Input/PS2Keyboard.cpp | 4 +- kernel/kernel/Shell.cpp | 2 +- 14 files changed, 121 insertions(+), 144 deletions(-) delete mode 100644 kernel/kernel/FS/Inode.cpp diff --git a/kernel/Makefile b/kernel/Makefile index a34a5f74..762715b3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -44,7 +44,6 @@ kernel/Debug.o \ kernel/Device.o \ kernel/Font.o \ kernel/FS/Ext2.o \ -kernel/FS/Inode.o \ kernel/FS/VirtualFileSystem.o \ kernel/Input/PS2Controller.o \ kernel/Input/PS2Keyboard.o \ diff --git a/kernel/include/kernel/Device.h b/kernel/include/kernel/Device.h index b1d83f6d..97d47c34 100644 --- a/kernel/include/kernel/Device.h +++ b/kernel/include/kernel/Device.h @@ -48,31 +48,12 @@ namespace Kernel void update(); void add_device(Device*); - virtual ino_t ino() const override { return 0; } - virtual mode_t mode() const override { return IFDIR | IRUSR | IWUSR | IXUSR | IRGRP | IXGRP | IROTH | IXOTH; } - virtual nlink_t nlink() const override { return 0; } - virtual uid_t uid() const override { return 0; } - virtual gid_t gid() const override { return 0; } - virtual off_t size() const override { return 0; } - virtual timespec atime() const override { return { 0, 0 }; } - virtual timespec mtime() const override { return { 0, 0 }; } - virtual timespec ctime() const override { return { 0, 0 }; } - virtual blksize_t blksize() const override { return 0; } - virtual blkcnt_t blocks() const override { return 0; } - - virtual BAN::StringView name() const override { return "device-manager"sv; } - - virtual BAN::ErrorOr read(size_t, void*, size_t) override { return BAN::Error::from_errno(EISDIR); } - virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) override { return BAN::Error::from_errno(EINVAL); }; - - virtual InodeType type() const override { return InodeType::DeviceManager; } - virtual bool operator==(const Inode&) const override { return false; } - virtual BAN::RefPtr root_inode() override { return this; } - protected: - virtual BAN::ErrorOr> read_directory_inode_impl(BAN::StringView) override; - virtual BAN::ErrorOr> read_directory_entries_impl(size_t) override; + virtual BAN::StringView name() const override { return "device-manager"; } + + virtual BAN::ErrorOr> read_directory_inode(BAN::StringView) override; + virtual BAN::ErrorOr> read_directory_entries(size_t) override; private: DeviceManager() = default; @@ -82,6 +63,24 @@ namespace Kernel BAN::Vector m_devices; friend class BAN::RefPtr; + + public: + virtual ino_t ino() const override { return 0; } + virtual mode_t mode() const override { return Mode::IFDIR | Mode::IRUSR | Mode::IWUSR | Mode::IXUSR | Mode::IRGRP | Mode::IXGRP | Mode::IROTH | Mode::IXOTH; } + virtual nlink_t nlink() const override { return 0; } + virtual uid_t uid() const override { return 0; } + virtual gid_t gid() const override { return 0; } + virtual off_t size() const override { return 0; } + virtual timespec atime() const override { return { 0, 0 }; } + virtual timespec mtime() const override { return { 0, 0 }; } + virtual timespec ctime() const override { return { 0, 0 }; } + virtual blksize_t blksize() const override { return 0; } + virtual blkcnt_t blocks() const override { return 0; } + virtual dev_t dev() const override { return 0x4935; } + virtual dev_t rdev() const override { return 0x7854; } + + virtual BAN::ErrorOr read(size_t, void*, size_t) { ASSERT_NOT_REACHED(); } + virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) { ASSERT_NOT_REACHED(); } }; } \ No newline at end of file diff --git a/kernel/include/kernel/FS/Ext2.h b/kernel/include/kernel/FS/Ext2.h index cc436ff6..43e86ea1 100644 --- a/kernel/include/kernel/FS/Ext2.h +++ b/kernel/include/kernel/FS/Ext2.h @@ -134,27 +134,24 @@ namespace Kernel virtual timespec ctime() const override { return timespec { .tv_sec = m_inode.ctime, .tv_nsec = 0 }; } virtual blksize_t blksize() const override; virtual blkcnt_t blocks() const override; + virtual dev_t dev() const override { return 0; } + virtual dev_t rdev() const override { return 0; } virtual BAN::StringView name() const override { return m_name; } virtual BAN::ErrorOr read(size_t, void*, size_t) override; - virtual BAN::ErrorOr> read_directory_entries_impl(size_t) override; + virtual BAN::ErrorOr> read_directory_entries(size_t) override; + virtual BAN::ErrorOr> read_directory_inode(BAN::StringView) override; virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) override; - virtual InodeType type() const override { return InodeType::Ext2; } - virtual bool operator==(const Inode& other) const override; - - protected: - virtual BAN::ErrorOr> read_directory_inode_impl(BAN::StringView) override; - private: BAN::ErrorOr data_block_index(uint32_t); uint32_t index() const { return m_index; } private: - Ext2Inode(Ext2FS& fs, Ext2::Inode inode, BAN::StringView name, uint32_t index) + Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t index, BAN::StringView name) : m_fs(fs) , m_inode(inode) , m_name(name) diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 1944e23f..861693a2 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -33,45 +33,35 @@ namespace Kernel IFREG = 0x8000, }; - enum class InodeType - { - DeviceManager, - Device, - Ext2, - }; - public: virtual ~Inode() {} bool ifdir() const { return mode() & Mode::IFDIR; } bool ifreg() const { return mode() & Mode::IFREG; } + bool operator==(const Inode& other) const { return dev() == other.dev() && rdev() == other.rdev() && ino() == other.ino(); } + virtual ino_t ino() const = 0; virtual mode_t mode() const = 0; virtual nlink_t nlink() const = 0; virtual uid_t uid() const = 0; virtual gid_t gid() const = 0; virtual off_t size() const = 0; - virtual timespec atime() const = 0; + virtual timespec atime() const = 0; virtual timespec mtime() const = 0; virtual timespec ctime() const = 0; virtual blksize_t blksize() const = 0; virtual blkcnt_t blocks() const = 0; + virtual dev_t dev() const = 0; + virtual dev_t rdev() const = 0; virtual BAN::StringView name() const = 0; - BAN::ErrorOr> read_directory_inode(BAN::StringView); - BAN::ErrorOr> read_directory_entries(size_t); + virtual BAN::ErrorOr> read_directory_inode(BAN::StringView) { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } + virtual BAN::ErrorOr> read_directory_entries(size_t) { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } - virtual BAN::ErrorOr read(size_t, void*, size_t) = 0; - virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) = 0; - - virtual InodeType type() const = 0; - virtual bool operator==(const Inode&) const = 0; - - protected: - virtual BAN::ErrorOr> read_directory_inode_impl(BAN::StringView) = 0; - virtual BAN::ErrorOr> read_directory_entries_impl(size_t) = 0; + virtual BAN::ErrorOr read(size_t, void*, size_t) { if ( ifdir()) return BAN::Error::from_errno(EISDIR); ASSERT_NOT_REACHED(); } + virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } }; } \ No newline at end of file diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 843becab..de7f9435 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -30,10 +30,10 @@ namespace Kernel struct MountPoint { - BAN::RefPtr inode; + File host; FileSystem* target; }; - const BAN::Vector& mount_points() const { return m_mount_points; } + MountPoint* mount_point_for_inode(BAN::RefPtr); private: VirtualFileSystem() = default; diff --git a/kernel/include/kernel/Input/PS2Controller.h b/kernel/include/kernel/Input/PS2Controller.h index 571f8316..6594b9fb 100644 --- a/kernel/include/kernel/Input/PS2Controller.h +++ b/kernel/include/kernel/Input/PS2Controller.h @@ -8,8 +8,27 @@ namespace Kernel::Input class PS2Device : public CharacterDevice { public: + PS2Device(dev_t); virtual ~PS2Device() {} virtual void on_byte(uint8_t) = 0; + + public: + virtual ino_t ino() const { return m_ino; } + virtual mode_t mode() const override { return Mode::IFCHR | Mode::IRUSR | Mode::IRGRP; } + virtual nlink_t nlink() const override { return 1; } + virtual uid_t uid() const override { return 0; } + virtual gid_t gid() const override { return 0; } + virtual off_t size() const override { return 0; } + virtual timespec atime() const override { return m_time; } + virtual timespec mtime() const override { return m_time; } + virtual timespec ctime() const override { return m_time; } + virtual blkcnt_t blocks() const override { return 0; } + virtual dev_t dev() const override { return m_dev; } + + private: + timespec m_time; + ino_t m_ino; + dev_t m_dev; }; class PS2Controller diff --git a/kernel/include/kernel/Input/PS2Keyboard.h b/kernel/include/kernel/Input/PS2Keyboard.h index 6c472c51..9d2ce9ce 100644 --- a/kernel/include/kernel/Input/PS2Keyboard.h +++ b/kernel/include/kernel/Input/PS2Keyboard.h @@ -26,14 +26,16 @@ namespace Kernel::Input }; public: - static BAN::ErrorOr create(PS2Controller&); + static BAN::ErrorOr create(PS2Controller&, dev_t); virtual void on_byte(uint8_t) override; virtual void update() override; private: - PS2Keyboard(PS2Controller& controller) - : m_controller(controller) + PS2Keyboard(PS2Controller& controller, dev_t device) + : PS2Device(device) + , m_controller(controller) + , m_name(BAN::String::formatted("input{}", device)) {} BAN::ErrorOr initialize(); @@ -58,30 +60,13 @@ namespace Kernel::Input State m_state { State::Normal }; + BAN::String m_name; + public: - virtual ino_t ino() const override { return 0; } - virtual mode_t mode() const override { return IFCHR | IRUSR | IRGRP; } - virtual nlink_t nlink() const override { return 0; } - virtual uid_t uid() const override { return 0; } - virtual gid_t gid() const override { return 0; } - virtual off_t size() const override { return 0; } - virtual timespec atime() const override { return { 0, 0 }; } - virtual timespec mtime() const override { return { 0, 0 }; } - virtual timespec ctime() const override { return { 0, 0 }; } + virtual BAN::StringView name() const override { return m_name; } virtual blksize_t blksize() const override { return sizeof(KeyEvent); } - virtual blkcnt_t blocks() const override { return 0; } - - virtual BAN::StringView name() const override { return "input"sv; } - + virtual dev_t rdev() const override { return 0x8594; } virtual BAN::ErrorOr read(size_t, void*, size_t) override; - virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) override { return BAN::Error::from_errno(ENOTDIR); } - - virtual InodeType type() const override { return InodeType::Device; } - virtual bool operator==(const Inode&) const override { return false; } - - protected: - virtual BAN::ErrorOr> read_directory_inode_impl(BAN::StringView) override { return BAN::Error::from_errno(ENOTDIR); } - virtual BAN::ErrorOr> read_directory_entries_impl(size_t) override { return BAN::Error::from_errno(ENOTDIR); } }; } \ No newline at end of file diff --git a/kernel/kernel/Device.cpp b/kernel/kernel/Device.cpp index 25db8bb8..fdfe0feb 100644 --- a/kernel/kernel/Device.cpp +++ b/kernel/kernel/Device.cpp @@ -45,7 +45,7 @@ namespace Kernel MUST(m_devices.push_back(device)); } - BAN::ErrorOr> DeviceManager::read_directory_inode_impl(BAN::StringView name) + BAN::ErrorOr> DeviceManager::read_directory_inode(BAN::StringView name) { LockGuard _(m_lock); for (Device* device : m_devices) @@ -54,7 +54,7 @@ namespace Kernel return BAN::Error::from_errno(ENOENT); } - BAN::ErrorOr> DeviceManager::read_directory_entries_impl(size_t index) + BAN::ErrorOr> DeviceManager::read_directory_entries(size_t index) { BAN::Vector result; if (index > 0) diff --git a/kernel/kernel/FS/Ext2.cpp b/kernel/kernel/FS/Ext2.cpp index f30d5666..cc59986c 100644 --- a/kernel/kernel/FS/Ext2.cpp +++ b/kernel/kernel/FS/Ext2.cpp @@ -169,7 +169,7 @@ namespace Kernel auto inode_location = TRY(fs.locate_inode(inode_inode)); fs.read_block(inode_location.block, block_buffer.span()); auto& inode = *(Ext2::Inode*)(block_buffer.data() + inode_location.offset); - Ext2Inode* result = new Ext2Inode(fs, inode, name, inode_inode); + Ext2Inode* result = new Ext2Inode(fs, inode, inode_inode, name); if (result == nullptr) return BAN::Error::from_errno(ENOMEM); return BAN::RefPtr::adopt(result); @@ -284,7 +284,7 @@ namespace Kernel return n_read; } - BAN::ErrorOr> Ext2Inode::read_directory_entries_impl(size_t index) + BAN::ErrorOr> Ext2Inode::read_directory_entries(size_t index) { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); @@ -328,7 +328,7 @@ namespace Kernel BAN::Vector block_buffer; TRY(block_buffer.resize(block_size)); - auto error_or = read_directory_inode_impl(name); + auto error_or = read_directory_inode(name); if (!error_or.is_error()) return BAN::Error::from_errno(EEXISTS); if (error_or.error().get_error_code() != ENOENT) @@ -401,7 +401,7 @@ namespace Kernel return {}; } - BAN::ErrorOr> Ext2Inode::read_directory_inode_impl(BAN::StringView file_name) + BAN::ErrorOr> Ext2Inode::read_directory_inode(BAN::StringView file_name) { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); @@ -425,7 +425,7 @@ namespace Kernel const auto& entry = *(const Ext2::LinkedDirectoryEntry*)entry_addr; BAN::StringView entry_name(entry.name, entry.name_len); if (entry.inode && entry_name == file_name) - return TRY(Ext2Inode::create(m_fs, entry.inode, entry.name)); + return TRY(Ext2Inode::create(m_fs, entry.inode, entry_name)); entry_addr += entry.rec_len; } } @@ -433,17 +433,6 @@ namespace Kernel return BAN::Error::from_errno(ENOENT); } - bool Ext2Inode::operator==(const Inode& other) const - { - if (type() != other.type()) - return false; - - const auto& ext2_other = (const Ext2Inode&)other; - if (&m_fs != &ext2_other.m_fs) - return false; - return index() == ext2_other.index(); - } - BAN::ErrorOr Ext2FS::create(Partition& partition) { Ext2FS* ext2fs = new Ext2FS(partition); diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp deleted file mode 100644 index bbe01a99..00000000 --- a/kernel/kernel/FS/Inode.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include - -namespace Kernel -{ - - BAN::ErrorOr> Inode::read_directory_inode(BAN::StringView name) - { - if (name == ".."sv) - return read_directory_inode_impl(name); - for (const auto& mount : VirtualFileSystem::get().mount_points()) - if (*mount.inode == *this) - return mount.target->root_inode()->read_directory_inode_impl(name); - return read_directory_inode_impl(name); - } - - BAN::ErrorOr> Inode::read_directory_entries(size_t index) - { - for (const auto& mount : VirtualFileSystem::get().mount_points()) - if (*mount.inode == *this) - return mount.target->root_inode()->read_directory_entries_impl(index); - return read_directory_entries_impl(index); - } - -} \ No newline at end of file diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index d3a65eb6..6d996886 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -144,10 +144,18 @@ namespace Kernel auto file = TRY(file_from_absolute_path(path)); if (!file.inode->ifdir()) return BAN::Error::from_errno(ENOTDIR); - TRY(m_mount_points.push_back({ file.inode, file_system })); + TRY(m_mount_points.push_back({ file, file_system })); return {}; } + VirtualFileSystem::MountPoint* VirtualFileSystem::mount_point_for_inode(BAN::RefPtr inode) + { + for (MountPoint& mount : m_mount_points) + if (*mount.host.inode == *inode) + return &mount; + return nullptr; + } + BAN::ErrorOr VirtualFileSystem::file_from_absolute_path(BAN::StringView path) { ASSERT(path.front() == '/'); @@ -156,39 +164,47 @@ namespace Kernel if (!inode) return BAN::Error::from_c_string("No root inode available"); - auto path_parts = TRY(path.split('/')); + BAN::String canonical_path; - for (size_t i = 0; i < path_parts.size();) + const auto path_parts = TRY(path.split('/')); + + for (const auto& path_part : path_parts) { - if (path_parts[i] == "."sv) + if (path_part.empty() || path_part == "."sv) { - path_parts.remove(i); + continue; } - else if (path_parts[i] == ".."sv) + else if (path_part == ".."sv) { - inode = TRY(inode->read_directory_inode(path_parts[i])); - path_parts.remove(i); - if (i > 0) + if (auto* mount_point = mount_point_for_inode(inode)) + inode = TRY(mount_point->host.inode->read_directory_inode(".."sv)); + else + inode = TRY(inode->read_directory_inode(".."sv)); + + if (!canonical_path.empty()) { - path_parts.remove(i - 1); - i--; + while (canonical_path.back() != '/') + canonical_path.pop_back(); + canonical_path.pop_back(); } } else { - inode = TRY(inode->read_directory_inode(path_parts[i])); - i++; + inode = TRY(inode->read_directory_inode(path_part)); + TRY(canonical_path.push_back('/')); + TRY(canonical_path.append(path_part)); } + + if (auto* mount_point = mount_point_for_inode(inode)) + inode = mount_point->target->root_inode(); } + if (canonical_path.empty()) + TRY(canonical_path.push_back('/')); + File file; file.inode = inode; - - for (const auto& part : path_parts) - { - TRY(file.canonical_path.push_back('/')); - TRY(file.canonical_path.append(part)); - } + file.canonical_path = BAN::move(canonical_path); if (file.canonical_path.empty()) TRY(file.canonical_path.push_back('/')); diff --git a/kernel/kernel/Input/PS2Controller.cpp b/kernel/kernel/Input/PS2Controller.cpp index 2d0ae56c..37b75393 100644 --- a/kernel/kernel/Input/PS2Controller.cpp +++ b/kernel/kernel/Input/PS2Controller.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,7 @@ #include #include #include +#include namespace Kernel::Input { @@ -301,7 +303,7 @@ namespace Kernel::Input // MF2 Keyboard if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83)) - m_devices[device] = TRY(PS2Keyboard::create(*this)); + m_devices[device] = TRY(PS2Keyboard::create(*this, device)); if (m_devices[device]) return {}; @@ -331,4 +333,11 @@ namespace Kernel::Input return {}; } + PS2Device::PS2Device(dev_t dev) + { + m_dev = dev; + m_ino = dev & 1; + m_time = { BAN::to_unix_time(RTC::get_current_time()), 0 }; + } + } \ No newline at end of file diff --git a/kernel/kernel/Input/PS2Keyboard.cpp b/kernel/kernel/Input/PS2Keyboard.cpp index ea5511d0..6e44e7bc 100644 --- a/kernel/kernel/Input/PS2Keyboard.cpp +++ b/kernel/kernel/Input/PS2Keyboard.cpp @@ -37,9 +37,9 @@ namespace Kernel::Input } - BAN::ErrorOr PS2Keyboard::create(PS2Controller& controller) + BAN::ErrorOr PS2Keyboard::create(PS2Controller& controller, dev_t device) { - PS2Keyboard* keyboard = new PS2Keyboard(controller); + PS2Keyboard* keyboard = new PS2Keyboard(controller, device); if (keyboard == nullptr) return BAN::Error::from_errno(ENOMEM); BAN::ScopeGuard guard([keyboard] { delete keyboard; }); diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index bc2468af..988c9e5b 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -98,7 +98,7 @@ namespace Kernel void Shell::run() { - int fd = MUST(Process::current()->open("/dev/input"sv, O_RDONLY)); + int fd = MUST(Process::current()->open("/dev/input0"sv, O_RDONLY)); TTY_PRINT("{}", m_prompt); for (;;)