diff --git a/disk.sh b/disk.sh index 88b97a76e5..b14645ad36 100755 --- a/disk.sh +++ b/disk.sh @@ -14,6 +14,10 @@ sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk $DISK_NAME 1 # partition number 1 # default (from the beginning of the disk) +1MiB # bios boot partiton size + n # new partition + 3 # partition number 3 + # default (right after bios boot partition) + +10Mib# partition size n # new partition 2 # partition number 2 # default (right after bios boot partition) @@ -26,6 +30,9 @@ sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk $DISK_NAME 20 # Linux filesystem x # expert menu n # partition name + 3 # ... of partition 3 + mount-test + n # partition name 2 # ... of partition 2 banan-root r # back to main menu @@ -37,6 +44,7 @@ sudo partprobe $LOOP_DEV PARTITION1=${LOOP_DEV}p1 PARTITION2=${LOOP_DEV}p2 +PARTITION3=${LOOP_DEV}p3 sudo mkfs.ext2 $PARTITION2 @@ -64,4 +72,10 @@ menuentry "banan-os (no apic, no serial)" { ' | sudo tee ${MOUNT_DIR}/boot/grub/grub.cfg sudo umount $MOUNT_DIR + +sudo mkfs.ext2 $PARTITION3 +sudo mount $PARTITION3 $MOUNT_DIR +echo 'hello' | sudo tee ${MOUNT_DIR}/hello.txt +sudo umount $MOUNT_DIR + sudo losetup -d $LOOP_DEV diff --git a/kernel/Makefile b/kernel/Makefile index c3169a56d0..2932e2ff1a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -42,6 +42,7 @@ kernel/CPUID.o \ kernel/Debug.o \ kernel/Font.o \ kernel/FS/Ext2.o \ +kernel/FS/Inode.o \ kernel/FS/VirtualFileSystem.o \ kernel/Input.o \ kernel/InterruptController.o \ diff --git a/kernel/include/kernel/FS/Ext2.h b/kernel/include/kernel/FS/Ext2.h index a9628b4264..caf791fbed 100644 --- a/kernel/include/kernel/FS/Ext2.h +++ b/kernel/include/kernel/FS/Ext2.h @@ -132,12 +132,14 @@ namespace Kernel virtual BAN::StringView name() const override { return m_name; } virtual BAN::ErrorOr read(size_t, void*, size_t) override; - virtual BAN::ErrorOr>> directory_inodes() override; - virtual BAN::ErrorOr> directory_find(BAN::StringView) override; virtual Type type() const override { return Type::Ext2; } virtual bool operator==(const Inode& other) const override; + protected: + virtual BAN::ErrorOr>> directory_inodes_impl() override; + virtual BAN::ErrorOr> directory_find_impl(BAN::StringView) override; + private: BAN::ErrorOr data_block_index(uint32_t); @@ -170,7 +172,7 @@ namespace Kernel public: static BAN::ErrorOr create(StorageDevice::Partition&); - virtual const BAN::RefPtr root_inode() const override { return m_root_inode; } + virtual BAN::RefPtr root_inode() override { return m_root_inode; } private: Ext2FS(StorageDevice::Partition& partition) diff --git a/kernel/include/kernel/FS/FileSystem.h b/kernel/include/kernel/FS/FileSystem.h index f188d224f6..9435870a98 100644 --- a/kernel/include/kernel/FS/FileSystem.h +++ b/kernel/include/kernel/FS/FileSystem.h @@ -9,7 +9,7 @@ namespace Kernel class FileSystem { public: - virtual const BAN::RefPtr root_inode() const = 0; + virtual BAN::RefPtr root_inode() = 0; }; } \ No newline at end of file diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 4ee00dcecb..827d66e001 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -1,9 +1,8 @@ #pragma once -#include #include - -#include +#include +#include namespace Kernel { @@ -37,7 +36,6 @@ namespace Kernel enum class Type { - General, Ext2, }; @@ -55,12 +53,17 @@ namespace Kernel virtual BAN::StringView name() const = 0; - virtual BAN::ErrorOr read(size_t, void*, size_t) = 0; - virtual BAN::ErrorOr>> directory_inodes() = 0; - virtual BAN::ErrorOr> directory_find(BAN::StringView) = 0; + BAN::ErrorOr>> directory_inodes(); + BAN::ErrorOr> directory_find(BAN::StringView); - virtual Type type() const { return Type::General; } + virtual BAN::ErrorOr read(size_t, void*, size_t) = 0; + + virtual Type type() const = 0; virtual bool operator==(const Inode&) const = 0; + + protected: + virtual BAN::ErrorOr>> directory_inodes_impl() = 0; + virtual BAN::ErrorOr> directory_find_impl(BAN::StringView) = 0; }; } \ No newline at end of file diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 3dc75ddd56..86b560df7f 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -15,7 +16,9 @@ namespace Kernel static VirtualFileSystem& get(); virtual ~VirtualFileSystem() {}; - virtual const BAN::RefPtr root_inode() const override { return m_root_inode; } + virtual BAN::RefPtr root_inode() override { return m_root_inode; } + + BAN::ErrorOr mount_test(); struct File { @@ -24,12 +27,20 @@ namespace Kernel }; BAN::ErrorOr file_from_absolute_path(BAN::StringView); + struct MountPoint + { + BAN::RefPtr inode; + FileSystem* target; + }; + const BAN::Vector& mount_points() const { return m_mount_points; } + private: VirtualFileSystem() = default; BAN::ErrorOr initialize_impl(); private: BAN::RefPtr m_root_inode; + BAN::Vector m_mount_points; BAN::Vector m_storage_controllers; }; diff --git a/kernel/kernel/FS/Ext2.cpp b/kernel/kernel/FS/Ext2.cpp index ccc6851005..2f85df7d66 100644 --- a/kernel/kernel/FS/Ext2.cpp +++ b/kernel/kernel/FS/Ext2.cpp @@ -263,7 +263,7 @@ namespace Kernel return count; } - BAN::ErrorOr> Ext2Inode::directory_find(BAN::StringView file_name) + BAN::ErrorOr> Ext2Inode::directory_find_impl(BAN::StringView file_name) { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); @@ -307,45 +307,42 @@ namespace Kernel return BAN::Error::from_errno(ENOENT); } - BAN::ErrorOr>> Ext2Inode::directory_inodes() + BAN::ErrorOr>> Ext2Inode::directory_inodes_impl() { if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); - struct directory_info + uint32_t data_block_count = m_inode.blocks / (2 << m_fs.superblock().log_block_size); + + BAN::Vector> inodes; + + for (uint32_t i = 0; i < data_block_count; i++) { - BAN::Vector> inodes; - Ext2FS* fs; - }; - - directory_info info; - info.inodes = {}; - info.fs = &m_fs; - - block_callback_t function = - [](const BAN::Vector& block_data, void* info_) -> BAN::ErrorOr + auto data_block_index_or_error = data_block_index(i); + if (data_block_index_or_error.is_error()) { - directory_info& info = *(directory_info*)info_; + dprintln("{}", data_block_index_or_error.error()); + continue; + } - uintptr_t block_data_end = (uintptr_t)block_data.data() + block_data.size(); - uintptr_t entry_addr = (uintptr_t)block_data.data(); - while (entry_addr < block_data_end) + auto block_data = TRY(m_fs.read_block(data_block_index_or_error.value())); + + uint8_t* block_data_end = block_data.data() + block_data.size(); + uint8_t* entry_addr = block_data.data(); + while (entry_addr < block_data_end) + { + Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr; + if (entry->inode) { - Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr; - if (entry->inode) - { - auto entry_name = BAN::StringView(entry->name, entry->name_len); - auto inode = TRY(Ext2Inode::create(*info.fs, entry->inode, entry_name)); - TRY(info.inodes.push_back(inode)); - } - entry_addr += entry->rec_len; + auto entry_name = BAN::StringView(entry->name, entry->name_len); + auto inode = TRY(Ext2Inode::create(m_fs, entry->inode, entry_name)); + TRY(inodes.push_back(inode)); } - return true; - }; + entry_addr += entry->rec_len; + } + } - TRY(for_each_block(function, &info)); - - return info.inodes; + return inodes; } bool Ext2Inode::operator==(const Inode& other) const diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp new file mode 100644 index 0000000000..361891b0c7 --- /dev/null +++ b/kernel/kernel/FS/Inode.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +namespace Kernel +{ + + + BAN::ErrorOr>> Inode::directory_inodes() + { + for (const auto& mount : VirtualFileSystem::get().mount_points()) + if (*mount.inode == *this) + return mount.target->root_inode()->directory_inodes_impl(); + return directory_inodes_impl(); + } + + BAN::ErrorOr> Inode::directory_find(BAN::StringView name) + { + if (name == ".."sv) + return directory_find_impl(name); + for (const auto& mount : VirtualFileSystem::get().mount_points()) + if (*mount.inode == *this) + return mount.target->root_inode()->directory_find_impl(name); + return directory_find_impl(name); + } + +} \ No newline at end of file diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 2379087872..95d35b61f1 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -115,6 +115,32 @@ namespace Kernel return {}; } + BAN::ErrorOr VirtualFileSystem::mount_test() + { + auto mount = TRY(root_inode()->directory_find("mnt"sv)); + if (!mount->ifdir()) + return BAN::Error::from_errno(ENOTDIR); + if (TRY(mount->directory_inodes()).size() > 2) + return BAN::Error::from_errno(ENOTEMPTY); + + for (auto* controller : m_storage_controllers) + { + for (auto* device : controller->devices()) + { + for (auto& partition : device->partitions()) + { + if (partition.name() == "mount-test"sv) + { + auto ext2fs = TRY(Ext2FS::create(partition)); + TRY(m_mount_points.push_back({ mount, ext2fs })); + return {}; + } + } + } + } + return {}; + } + BAN::ErrorOr VirtualFileSystem::file_from_absolute_path(BAN::StringView path) { ASSERT(path.front() == '/'); @@ -143,7 +169,7 @@ namespace Kernel } else { - inode = TRY(inode->directory_find(path_parts[i])); + inode = TRY(inode->directory_find(path_parts[i])); i++; } } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 772dba59fa..5cec6939ff 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -195,6 +195,8 @@ void init2(void* tty1_ptr) TTY* tty1 = (TTY*)tty1_ptr; MUST(VirtualFileSystem::initialize()); + if (auto res = VirtualFileSystem::get().mount_test(); res.is_error()) + dwarnln("{}", res.error()); MUST(Process::create_kernel( [](void* tty1)