diff options
| author | Marcel Braun <marcel.braun@ost.ch> | 2026-05-16 14:20:38 +0200 |
|---|---|---|
| committer | Marcel Braun <marcel.braun@ost.ch> | 2026-05-16 14:20:38 +0200 |
| commit | 106e9731aaf856f940592c02953e49a496555822 (patch) | |
| tree | f3916a9865d03ebb574bac7d5496f6ec85d638ed /kernel | |
| parent | d22812dbf54a9fd8ecd558a94bf4ee789caf8011 (diff) | |
| parent | 5b40e4a28307eed814adb46188c3f6783651d286 (diff) | |
| download | kernel-106e9731aaf856f940592c02953e49a496555822.tar.xz kernel-106e9731aaf856f940592c02953e49a496555822.zip | |
Merge branch 'mount-reference-count' into 'develop-BA-FS26'
Mount reference count
See merge request teachos/kernel!37
Diffstat (limited to 'kernel')
24 files changed, 357 insertions, 222 deletions
diff --git a/kernel/include/kernel/filesystem/dentry.hpp b/kernel/include/kernel/filesystem/dentry.hpp index 7eef693..925768a 100644 --- a/kernel/include/kernel/filesystem/dentry.hpp +++ b/kernel/include/kernel/filesystem/dentry.hpp @@ -24,8 +24,7 @@ namespace kernel::filesystem */ enum class dentry_flags : uint32_t { - is_mount_point = 1 << 0, - is_mount_root = 1 << 1, + is_mount_point = 1 << 0 }; /** @@ -62,12 +61,6 @@ namespace kernel::filesystem [[nodiscard]] auto get_absolute_path() const -> kstd::string; /** - @brief traverse parent dentries until dentry with is_mount_root flag is found. - @return The found dentry. - */ - [[nodiscard]] auto find_mount_root_dentry() const -> kstd::shared_ptr<dentry>; - - /** @brief Add a @p child dentry. @param child The child dentry to add. */ @@ -104,7 +97,7 @@ namespace kernel::filesystem kstd::shared_ptr<dentry> m_parent; kstd::vector<kstd::shared_ptr<dentry>> m_children; kstd::shared_ptr<inode> m_inode; - uint32_t m_flags{0}; + uint32_t m_flags; }; } // namespace kernel::filesystem diff --git a/kernel/include/kernel/filesystem/mount.hpp b/kernel/include/kernel/filesystem/mount.hpp index f920891..5d8ea69 100644 --- a/kernel/include/kernel/filesystem/mount.hpp +++ b/kernel/include/kernel/filesystem/mount.hpp @@ -8,6 +8,7 @@ #include <kstd/string> #include <atomic> +#include <cstddef> namespace kernel::filesystem { @@ -54,12 +55,35 @@ namespace kernel::filesystem */ [[nodiscard]] auto get_parent_mount() const -> kstd::shared_ptr<mount> const &; + /** + @brief Increment the reference count for this mount. + */ + auto increment_ref_count() -> void; + + /** + @brief Decrement the reference count for this mount. + @return True if the reference count reached zero, false otherwise. + */ + auto decrement_ref_count() -> bool; + + /** + @brief Check if the mount is ready to be unmounted. + @return True if the mount is ready to be unmounted, false otherwise. + */ + [[nodiscard]] auto is_ready_to_unmount() const -> bool; + + /** + @brief Get the current reference count for this mount. + @return The current reference count. + */ + [[nodiscard]] auto get_ref_count() const -> size_t; + private: kstd::shared_ptr<dentry> m_mount_dentry; kstd::shared_ptr<dentry> m_root_dentry; kstd::shared_ptr<filesystem> m_filesystem{}; kstd::shared_ptr<mount> m_parent_mount{}; - std::atomic_uint32_t m_ref_count{0}; // TODO BA-FS26 + std::atomic_size_t m_ref_count; }; } // namespace kernel::filesystem diff --git a/kernel/include/kernel/filesystem/mount_table.hpp b/kernel/include/kernel/filesystem/mount_table.hpp index 59b9503..4f2d1b7 100644 --- a/kernel/include/kernel/filesystem/mount_table.hpp +++ b/kernel/include/kernel/filesystem/mount_table.hpp @@ -22,7 +22,8 @@ namespace kernel::filesystem { removed = 0, has_child_mounts = -1, - mount_not_found = -2 + mount_not_found = -2, + cannot_be_unmounted = -3 }; /** @@ -43,10 +44,12 @@ namespace kernel::filesystem @param path The path to match against the mount paths in the table. @return A pointer to the mount with the exact matching path, or a null pointer if no mount matches the path. */ - [[nodiscard]] auto find_exact_mount(std::string_view path) const -> kstd::shared_ptr<mount>; + [[nodiscard]] auto find_mount(std::string_view path) const -> kstd::shared_ptr<mount>; private: [[nodiscard]] auto has_child_mounts(kstd::shared_ptr<mount> const & parent_mount) const -> bool; + [[nodiscard]] auto find_mount_iterator(std::string_view path) const + -> kstd::vector<kstd::shared_ptr<mount>>::const_iterator; kstd::vector<kstd::shared_ptr<mount>> m_mounts; }; diff --git a/kernel/include/kernel/filesystem/open_file_descriptor.hpp b/kernel/include/kernel/filesystem/open_file_descriptor.hpp index 036dcf0..7ca7350 100644 --- a/kernel/include/kernel/filesystem/open_file_descriptor.hpp +++ b/kernel/include/kernel/filesystem/open_file_descriptor.hpp @@ -1,7 +1,7 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTOR_HPP #define TEACH_OS_KERNEL_FILESYSTEM_OPEN_FILE_DESCRIPTOR_HPP -#include <kernel/filesystem/inode.hpp> +#include <kernel/filesystem/dentry.hpp> #include <kstd/memory> @@ -11,15 +11,15 @@ namespace kernel::filesystem { /** @brief Represents an open file descriptor in the filesystem. This class encapsulates the state of an open file, - including a reference to the associated inode and the current file offset. + including a reference to the associated dentry and the current file offset. */ struct open_file_descriptor { /** - @brief Constructs an open file descriptor for the given @p inode. - @param inode The inode to associate with the open file descriptor. + @brief Constructs an open file descriptor for the given @p dentry. + @param dentry The dentry to associate with the open file descriptor. */ - explicit open_file_descriptor(kstd::shared_ptr<inode> const & inode); + explicit open_file_descriptor(kstd::shared_ptr<dentry> const & dentry); /** @brief Destructor for the open file descriptor. @@ -50,10 +50,16 @@ namespace kernel::filesystem @brief Returns the current file offset for this open file descriptor. @return The current file offset in bytes. */ - [[nodiscard]] auto offset() const -> size_t; + [[nodiscard]] auto get_offset() const -> size_t; + + /** + @brief Return a reference to the dentry associated with this open file descriptor. + @return A reference to the associated dentry. + */ + [[nodiscard]] auto get_dentry() const -> kstd::shared_ptr<dentry> const &; private: - kstd::shared_ptr<inode> m_inode; + kstd::shared_ptr<dentry> m_dentry; size_t m_offset; }; diff --git a/kernel/include/kernel/filesystem/rootfs/filesystem.hpp b/kernel/include/kernel/filesystem/rootfs/filesystem.hpp index cc778d8..f99440b 100644 --- a/kernel/include/kernel/filesystem/rootfs/filesystem.hpp +++ b/kernel/include/kernel/filesystem/rootfs/filesystem.hpp @@ -31,7 +31,7 @@ namespace kernel::filesystem::rootfs @brief Looks up an inode by @p name within a @p parent directory. @param parent The parent directory inode. @param name The name of the inode to look up. - @return A pointer to the found inode, or a null pointer if not found. + @return Always returns nullptr. */ auto lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) -> kstd::shared_ptr<kernel::filesystem::inode> override; diff --git a/kernel/include/kernel/filesystem/rootfs/inode.hpp b/kernel/include/kernel/filesystem/rootfs/inode.hpp index 58035ea..2671207 100644 --- a/kernel/include/kernel/filesystem/rootfs/inode.hpp +++ b/kernel/include/kernel/filesystem/rootfs/inode.hpp @@ -8,16 +8,10 @@ #include <kstd/vector> #include <cstddef> -#include <string_view> -#include <utility> - namespace kernel::filesystem::rootfs { /** - @brief Represents an inode in the rootfs filesystem. This inode represents a directory in the root filesystem and - maintains a list of child inodes corresponding to files and subdirectories within the root directory. The rootfs inode - provides methods for reading and writing data (which are no-ops for the root directory), as well as adding and looking - up child inodes by name. + @brief Represents an inode in the rootfs filesystem. */ struct inode : kernel::filesystem::inode { @@ -40,26 +34,10 @@ namespace kernel::filesystem::rootfs auto write(void const * buffer, size_t offset, size_t size) -> size_t override; /** - @brief Adds a child inode to the rootfs directory inode with the specified @p name. - @param name The name of the child inode. - */ - auto add_child(std::string_view name) -> void; - - /** - @brief Looks up a child inode by @p name. - @param name The name of the child inode to look up. - @return A pointer to the found child inode, or a null pointer if not found. - */ - auto lookup_child(std::string_view name) -> kstd::shared_ptr<inode>; - - /** @brief Check if this inode represents a directory. - @return returns true, since this inode represents the root directory in the rootfs filesystem. + @return returns true, since this inode represents the / directory in the rootfs filesystem. */ [[nodiscard]] auto is_directory() const -> bool override; - - private: - kstd::vector<std::pair<kstd::string, kstd::shared_ptr<inode>>> m_children; }; } // namespace kernel::filesystem::rootfs diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index b5053a2..0058d04 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -1,14 +1,16 @@ #ifndef TEACH_OS_KERNEL_FILESYSTEM_VFS_HPP #define TEACH_OS_KERNEL_FILESYSTEM_VFS_HPP -#include "kernel/filesystem/devfs/filesystem.hpp" #include <kernel/filesystem/dentry.hpp> +#include <kernel/filesystem/devfs/filesystem.hpp> #include <kernel/filesystem/filesystem.hpp> +#include <kernel/filesystem/mount.hpp> #include <kernel/filesystem/mount_table.hpp> #include <kstd/memory> #include <string_view> +#include <utility> namespace kernel::filesystem { @@ -31,6 +33,7 @@ namespace kernel::filesystem mount_point_not_found = -3, unmount_failed = -4, invalid_filesystem = -5, + close_failed = -6 }; /** @@ -59,6 +62,13 @@ namespace kernel::filesystem auto open(std::string_view path) -> kstd::shared_ptr<dentry>; /** + @brief Close a file by its associated @p path. + @param path The path to the file to close. + @return The result of the close operation. + */ + auto close(std::string_view path) -> operation_result; + + /** @brief Mount a @p source path to a specific @p target path. @param source The source of the filesystem to mount. @param target The path where the filesystem should be mounted. @@ -77,8 +87,23 @@ namespace kernel::filesystem vfs() = default; auto init_internal() -> void; + /** + * Note: Resolving a dentry requires traversing mount points; since the + * associated 'mount' object is discovered as a byproduct of this + * traversal, we return it alongside the dentry to avoid redundant + * lookups in callers that require mount context. + * + * If only one component is needed, the convenience wrappers can be used: + * - resolve_path() for the dentry only. + * - find_mount() for the mount context only. + */ + [[nodiscard]] auto resolve_path_internal(std::string_view path) + -> std::pair<kstd::shared_ptr<dentry>, kstd::shared_ptr<mount>>; [[nodiscard]] auto resolve_path(std::string_view path) -> kstd::shared_ptr<dentry>; - auto do_mount_internal(kstd::shared_ptr<dentry> const & mount_point_dentry, kstd::shared_ptr<filesystem> const & fs) + [[nodiscard]] auto find_mount(std::string_view path) -> kstd::shared_ptr<mount>; + + auto do_mount_internal(kstd::shared_ptr<dentry> const & mount_point_dentry, + kstd::shared_ptr<mount> const & parent_mount, kstd::shared_ptr<filesystem> const & fs) -> void; auto graft_persistent_device_fs(kstd::shared_ptr<devfs::filesystem> const & device_fs) -> void; diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index 4c68f28..53a71be 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -35,7 +35,7 @@ namespace kapi::filesystem { if (auto dentry = kernel::filesystem::vfs::get().open(path)) { - auto open_file_descriptor = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry->get_inode()); + auto open_file_descriptor = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); return kernel::filesystem::open_file_table::get().add_file(open_file_descriptor); } @@ -44,7 +44,15 @@ namespace kapi::filesystem auto close(int file_descriptor) -> int { - return kernel::filesystem::open_file_table::get().remove_file(file_descriptor); + if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().get_file(file_descriptor)) + { + if (kernel::filesystem::vfs::get().close(open_file_descriptor->get_dentry()->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success) + { + return kernel::filesystem::open_file_table::get().remove_file(file_descriptor); + } + } + return -1; } auto read(int file_descriptor, void * buffer, size_t size) -> ssize_t diff --git a/kernel/kapi/filesystem.tests.cpp b/kernel/kapi/filesystem.tests.cpp index 1d1f8ee..d241afa 100644 --- a/kernel/kapi/filesystem.tests.cpp +++ b/kernel/kapi/filesystem.tests.cpp @@ -103,6 +103,19 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap REQUIRE(kapi::filesystem::umount("/information") == 0); } + THEN("a filesystem cannot be unmounted if files are still open and can be unmounted after files are closed") + { + REQUIRE(kapi::filesystem::mount("/dev/ram16", "/information") == 0); + + auto fd = kapi::filesystem::open("/information/monkey_house/monkey_1.txt"); + REQUIRE(fd >= 0); + + REQUIRE(kapi::filesystem::umount("/information") < 0); + + REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::umount("/information") == 0); + } + THEN("device can be opened as file and read from") { auto fd = kapi::filesystem::open("/dev/ram0"); @@ -158,6 +171,15 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Kap REQUIRE(kapi::filesystem::close(999) < 0); } + THEN("same file cannot be closed twice") + { + auto fd = kapi::filesystem::open("/information/info_1.txt"); + REQUIRE(fd >= 0); + + REQUIRE(kapi::filesystem::close(fd) == 0); + REQUIRE(kapi::filesystem::close(fd) < 0); + } + THEN("not opened files cannot be read from") { std::vector<std::byte> buffer(10); diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp index c21771b..d963ed7 100644 --- a/kernel/src/filesystem/dentry.cpp +++ b/kernel/src/filesystem/dentry.cpp @@ -17,6 +17,7 @@ namespace kernel::filesystem : m_name(name) , m_parent(parent) , m_inode(inode) + , m_flags(0) { if (!m_inode) { @@ -66,16 +67,6 @@ namespace kernel::filesystem return path; } - auto dentry::find_mount_root_dentry() const -> kstd::shared_ptr<dentry> - { - auto parent = m_parent; - while (parent && !parent->has_flag(dentry_flags::is_mount_root)) - { - parent = parent->get_parent(); - } - return parent; - } - auto dentry::add_child(kstd::shared_ptr<dentry> const & child) -> void { m_children.push_back(child); diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp index 45bea51..efc0660 100644 --- a/kernel/src/filesystem/ext2/inode.tests.cpp +++ b/kernel/src/filesystem/ext2/inode.tests.cpp @@ -1,9 +1,9 @@ #include <kernel/filesystem/ext2/inode.hpp> -#include "kernel/filesystem/ext2/superblock.hpp" #include <kernel/devices/storage/management.hpp> #include <kernel/filesystem/device_inode.hpp> #include <kernel/filesystem/ext2/filesystem.hpp> +#include <kernel/filesystem/ext2/superblock.hpp> #include <kernel/filesystem/filesystem.hpp> #include <kernel/test_support/cpu.hpp> #include <kernel/test_support/devices/block_device.hpp> diff --git a/kernel/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 749c86a..1e04083 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -8,6 +8,7 @@ #include <kstd/memory> #include <kstd/string> +#include <cstddef> #include <string_view> namespace kernel::filesystem @@ -18,6 +19,7 @@ namespace kernel::filesystem , m_root_dentry(root_dentry) , m_filesystem(fs) , m_parent_mount(parent_mount) + , m_ref_count(0) { if (!m_filesystem) { @@ -53,4 +55,30 @@ namespace kernel::filesystem { return m_parent_mount; } + + auto mount::increment_ref_count() -> void + { + m_ref_count += 1; + } + + auto mount::decrement_ref_count() -> bool + { + if (m_ref_count == 0) + { + return false; + } + + m_ref_count -= 1; + return true; + } + + auto mount::is_ready_to_unmount() const -> bool + { + return m_ref_count == 0; + } + + auto mount::get_ref_count() const -> size_t + { + return m_ref_count; + } } // namespace kernel::filesystem
\ No newline at end of file diff --git a/kernel/src/filesystem/mount.tests.cpp b/kernel/src/filesystem/mount.tests.cpp index 58e9bab..e7dd709 100644 --- a/kernel/src/filesystem/mount.tests.cpp +++ b/kernel/src/filesystem/mount.tests.cpp @@ -29,6 +29,7 @@ SCENARIO("Mount construction", "[filesystem][mount]") REQUIRE(mount.get_root_dentry() == root_dentry); REQUIRE(mount.get_mount_dentry() == root_dentry); REQUIRE(mount.get_mount_path() == "/"); + REQUIRE(mount.is_ready_to_unmount()); } THEN("the mount has no parent mount") @@ -47,3 +48,44 @@ SCENARIO("Mount construction", "[filesystem][mount]") } } } + +SCENARIO("Mount reference counting", "[filesystem][mount]") +{ + GIVEN("a filesystem and a root dentry") + { + auto fs = kstd::make_shared<kernel::tests::filesystem::filesystem>(); + auto root_inode = kstd::make_shared<kernel::tests::filesystem::inode>(); + auto root_dentry = kstd::make_shared<kernel::filesystem::dentry>(nullptr, root_inode, "/"); + + THEN("reference count can be incremented and decremented, the mount is ready to unmount when the reference " + "count == 0") + { + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + + mount.increment_ref_count(); + REQUIRE(mount.get_ref_count() == 1); + REQUIRE_FALSE(mount.is_ready_to_unmount()); + + mount.increment_ref_count(); + REQUIRE(mount.get_ref_count() == 2); + REQUIRE_FALSE(mount.is_ready_to_unmount()); + + REQUIRE(mount.decrement_ref_count()); + REQUIRE(mount.get_ref_count() == 1); + REQUIRE_FALSE(mount.is_ready_to_unmount()); + + REQUIRE(mount.decrement_ref_count()); + REQUIRE(mount.get_ref_count() == 0); + REQUIRE(mount.is_ready_to_unmount()); + } + + THEN("decrementing reference count when it is already zero does not decrement it below zero") + { + auto mount = kernel::filesystem::mount{root_dentry, root_dentry, fs, nullptr}; + + REQUIRE_FALSE(mount.decrement_ref_count()); + REQUIRE(mount.get_ref_count() == 0); + REQUIRE(mount.is_ready_to_unmount()); + } + } +}
\ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index 5a49e7a..9951590 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -26,25 +26,21 @@ namespace kernel::filesystem { mount_dentry->set_flag(dentry::dentry_flags::is_mount_point); } - if (auto root_dentry = mount->get_root_dentry()) - { - root_dentry->set_flag(dentry::dentry_flags::is_mount_root); - } } auto mount_table::remove_mount(std::string_view path) -> operation_result { - // TODO BA-FS26 check wheter something is open in this mount - auto mount_range = - std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); - auto mount_it = mount_range.begin(); - + auto mount_it = find_mount_iterator(path); if (mount_it == m_mounts.end()) { return operation_result::mount_not_found; } auto const & mount = *mount_it; + if (!mount->is_ready_to_unmount()) + { + return operation_result::cannot_be_unmounted; + } if (has_child_mounts(mount)) { return operation_result::has_child_mounts; @@ -55,11 +51,16 @@ namespace kernel::filesystem return operation_result::removed; } - auto mount_table::find_exact_mount(std::string_view path) const -> kstd::shared_ptr<mount> + auto mount_table::find_mount(std::string_view path) const -> kstd::shared_ptr<mount> { - auto mount_range = - std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }); - auto mount_it = mount_range.begin(); + auto mount_it = find_mount_iterator(path); return (mount_it != m_mounts.end()) ? *mount_it : nullptr; } + + auto mount_table::find_mount_iterator(std::string_view path) const + -> kstd::vector<kstd::shared_ptr<mount>>::const_iterator + { + return std::ranges::find_last_if(m_mounts, [&](auto const & mount) { return mount->get_mount_path() == path; }) + .begin(); + } } // namespace kernel::filesystem
\ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.tests.cpp b/kernel/src/filesystem/mount_table.tests.cpp index 4ae8711..f22b25e 100644 --- a/kernel/src/filesystem/mount_table.tests.cpp +++ b/kernel/src/filesystem/mount_table.tests.cpp @@ -58,14 +58,14 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("finding mounts by exact valid path returns the correct mount") { - REQUIRE(table.find_exact_mount("/") == mount1); - REQUIRE(table.find_exact_mount("/mnt") == mount2); + REQUIRE(table.find_mount("/") == mount1); + REQUIRE(table.find_mount("/mnt") == mount2); } THEN("finding mounts by exact invalid path returns null") { - REQUIRE(table.find_exact_mount("/nonexistent") == nullptr); - REQUIRE(table.find_exact_mount("/mnt/file") == nullptr); + REQUIRE(table.find_mount("/nonexistent") == nullptr); + REQUIRE(table.find_mount("/mnt/file") == nullptr); } THEN("removing a mount that has no child mounts succeeds") @@ -103,7 +103,7 @@ SCENARIO("Adding, finding and removing mounts in the mount table", "[filesystem] THEN("finding mounts by exact valid path returns the correct mount") { - REQUIRE(table.find_exact_mount("/") == mount2); + REQUIRE(table.find_mount("/") == mount2); } THEN("removing the topmost mount with the same path succeeds") diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp index 25bffbd..ebaabef 100644 --- a/kernel/src/filesystem/open_file_descriptor.cpp +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -1,6 +1,7 @@ -#include <kernel/filesystem/inode.hpp> #include <kernel/filesystem/open_file_descriptor.hpp> +#include <kernel/filesystem/dentry.hpp> + #include <kstd/memory> #include <kstd/os/error.hpp> @@ -8,33 +9,38 @@ namespace kernel::filesystem { - open_file_descriptor::open_file_descriptor(kstd::shared_ptr<inode> const & inode) - : m_inode(inode) + open_file_descriptor::open_file_descriptor(kstd::shared_ptr<dentry> const & dentry) + : m_dentry(dentry) , m_offset(0) { - if (!inode) + if (!dentry) { - kstd::os::panic("[FILESYSTEM] open_file_descriptor constructed with null inode."); + kstd::os::panic("[FILESYSTEM] open_file_descriptor constructed with null dentry."); } } auto open_file_descriptor::read(void * buffer, size_t size) -> size_t { - auto read_bytes = m_inode->read(buffer, m_offset, size); + auto read_bytes = m_dentry->get_inode()->read(buffer, m_offset, size); m_offset += read_bytes; return read_bytes; } auto open_file_descriptor::write(void const * buffer, size_t size) -> size_t { - auto written_bytes = m_inode->write(buffer, m_offset, size); + auto written_bytes = m_dentry->get_inode()->write(buffer, m_offset, size); m_offset += written_bytes; return written_bytes; } - auto open_file_descriptor::offset() const -> size_t + auto open_file_descriptor::get_offset() const -> size_t { return m_offset; } + auto open_file_descriptor::get_dentry() const -> kstd::shared_ptr<dentry> const & + { + return m_dentry; + } + } // namespace kernel::filesystem
\ No newline at end of file diff --git a/kernel/src/filesystem/open_file_descriptor.tests.cpp b/kernel/src/filesystem/open_file_descriptor.tests.cpp index 53835ba..1910b8b 100644 --- a/kernel/src/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -1,5 +1,7 @@ #include <kernel/filesystem/open_file_descriptor.hpp> +#include <kernel/filesystem/dentry.hpp> +#include <kernel/filesystem/inode.hpp> #include <kernel/filesystem/vfs.hpp> #include <kernel/test_support/filesystem/inode.hpp> #include <kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp> @@ -16,51 +18,53 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor]") { - GIVEN("an inode and an open file descriptor for that inode") + GIVEN("a dentry and an open file descriptor for that dentry") { auto inode = kstd::make_shared<kernel::tests::filesystem::inode>(); - auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + auto dentry = kstd::make_shared<kernel::filesystem::dentry>(nullptr, inode, "test_dentry"); + auto file_descriptor = kernel::filesystem::open_file_descriptor{dentry}; THEN("the initial offset is zero") { - REQUIRE(file_descriptor.offset() == 0); + REQUIRE(file_descriptor.get_offset() == 0); } } } SCENARIO("Open file descriptor read/write offset management", "[filesystem][open_file_descriptor]") { - GIVEN("an inode that tracks read/write calls and an open file descriptor for that inode") + GIVEN("a dentry that tracks read/write calls and an open file descriptor for that dentry") { auto inode = kstd::make_shared<kernel::tests::filesystem::inode>(); - auto file_descriptor = kernel::filesystem::open_file_descriptor{inode}; + auto dentry = kstd::make_shared<kernel::filesystem::dentry>(nullptr, inode, "test_dentry"); + auto file_descriptor = kernel::filesystem::open_file_descriptor{dentry}; THEN("the offset is updated correctly after reads") { REQUIRE(file_descriptor.read(nullptr, 100) == 100); - REQUIRE(file_descriptor.offset() == 100); + REQUIRE(file_descriptor.get_offset() == 100); REQUIRE(file_descriptor.read(nullptr, 50) == 50); - REQUIRE(file_descriptor.offset() == 150); + REQUIRE(file_descriptor.get_offset() == 150); } THEN("the offset is updated correctly after writes") { REQUIRE(file_descriptor.write(nullptr, 200) == 200); - REQUIRE(file_descriptor.offset() == 200); + REQUIRE(file_descriptor.get_offset() == 200); REQUIRE(file_descriptor.write(nullptr, 25) == 25); - REQUIRE(file_descriptor.offset() == 225); + REQUIRE(file_descriptor.get_offset() == 225); } THEN("reads and writes both update the same offset") { REQUIRE(file_descriptor.read(nullptr, 10) == 10); - REQUIRE(file_descriptor.offset() == 10); + REQUIRE(file_descriptor.get_offset() == 10); REQUIRE(file_descriptor.write(nullptr, 20) == 20); - REQUIRE(file_descriptor.offset() == 30); + REQUIRE(file_descriptor.get_offset() == 30); REQUIRE(file_descriptor.read(nullptr, 5) == 5); - REQUIRE(file_descriptor.offset() == 35); + REQUIRE(file_descriptor.get_offset() == 35); REQUIRE(file_descriptor.write(nullptr, 15) == 15); - REQUIRE(file_descriptor.offset() == 50); + REQUIRE(file_descriptor.get_offset() == 50); } } } @@ -78,14 +82,14 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope auto & vfs = kernel::filesystem::vfs::get(); auto dentry = vfs.open("/information/info_1.txt"); REQUIRE(dentry != nullptr); - auto ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry->get_inode()); + auto ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); THEN("the file can be read and the offset is updated") { kstd::vector<std::byte> buffer(32); auto bytes_read = ofd->read(buffer.data(), buffer.size()); REQUIRE(bytes_read == 7); - REQUIRE(ofd->offset() == 7); + REQUIRE(ofd->get_offset() == 7); std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)}; REQUIRE(buffer_as_str == "info_1\n"); @@ -96,11 +100,11 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope kstd::vector<std::byte> buffer(4); auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2); REQUIRE(bytes_read_1 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size() / 2); + REQUIRE(ofd->get_offset() == buffer.size() / 2); auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); REQUIRE(bytes_read_2 == buffer.size() / 2); - REQUIRE(ofd->offset() == buffer.size()); + REQUIRE(ofd->get_offset() == buffer.size()); std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read_1 + bytes_read_2}; REQUIRE(buffer_as_str == "info"); diff --git a/kernel/src/filesystem/open_file_table.tests.cpp b/kernel/src/filesystem/open_file_table.tests.cpp index a5c791d..456d6b7 100644 --- a/kernel/src/filesystem/open_file_table.tests.cpp +++ b/kernel/src/filesystem/open_file_table.tests.cpp @@ -1,5 +1,6 @@ #include <kernel/filesystem/open_file_table.hpp> +#include <kernel/filesystem/dentry.hpp> #include <kernel/filesystem/open_file_descriptor.hpp> #include <kernel/test_support/filesystem/inode.hpp> @@ -15,8 +16,10 @@ SCENARIO("Open file table add/get file", "[filesystem][open_file_table]") { auto & table = kernel::filesystem::open_file_table::get(); auto inode = kstd::make_shared<kernel::tests::filesystem::inode>(); - auto file_descriptor_1 = kstd::make_shared<kernel::filesystem::open_file_descriptor>(inode); - auto file_descriptor_2 = kstd::make_shared<kernel::filesystem::open_file_descriptor>(inode); + auto dentry = kstd::make_shared<kernel::filesystem::dentry>(nullptr, inode, "test_dentry"); + + auto file_descriptor_1 = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); + auto file_descriptor_2 = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); WHEN("adding the open file descriptor to the open file table") { @@ -69,7 +72,8 @@ SCENARIO("Open file table remove file", "[filesystem][open_file_table]") { auto & table = kernel::filesystem::open_file_table::get(); auto inode = kstd::make_shared<kernel::tests::filesystem::inode>(); - auto file_descriptor = kstd::make_shared<kernel::filesystem::open_file_descriptor>(inode); + auto dentry = kstd::make_shared<kernel::filesystem::dentry>(nullptr, inode, "test_dentry"); + auto file_descriptor = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); auto fd = table.add_file(file_descriptor); WHEN("removing the file descriptor using the file descriptor") diff --git a/kernel/src/filesystem/rootfs/filesystem.cpp b/kernel/src/filesystem/rootfs/filesystem.cpp index 6187c3c..d49e237 100644 --- a/kernel/src/filesystem/rootfs/filesystem.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.cpp @@ -11,18 +11,13 @@ namespace kernel::filesystem::rootfs { auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> operation_result { - auto rfs_inode = kstd::make_shared<inode>(); - rfs_inode->add_child("dev"); - m_root_inode = rfs_inode; - + m_root_inode = kstd::make_shared<inode>(); return operation_result::success; } - auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) + auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const &, std::string_view) -> kstd::shared_ptr<kernel::filesystem::inode> { - if (auto * rfs_inode = static_cast<inode *>(parent.get())) - return rfs_inode->lookup_child(name); return nullptr; } } // namespace kernel::filesystem::rootfs diff --git a/kernel/src/filesystem/rootfs/filesystem.tests.cpp b/kernel/src/filesystem/rootfs/filesystem.tests.cpp index 81ac9e4..ae320e9 100644 --- a/kernel/src/filesystem/rootfs/filesystem.tests.cpp +++ b/kernel/src/filesystem/rootfs/filesystem.tests.cpp @@ -21,13 +21,6 @@ SCENARIO("Rootfs filesystem mount and lookup", "[filesystem][rootfs][filesystem] REQUIRE(fs.root_inode() != nullptr); } - THEN("looking up the 'dev' directory returns a valid inode") - { - auto dev_inode = fs.lookup(fs.root_inode(), "dev"); - REQUIRE(dev_inode != nullptr); - REQUIRE(dev_inode->is_directory()); - } - THEN("looking up a non-existent directory returns null") { auto non_existent_inode_1 = fs.lookup(fs.root_inode(), ""); diff --git a/kernel/src/filesystem/rootfs/inode.cpp b/kernel/src/filesystem/rootfs/inode.cpp index d099676..dbe7948 100644 --- a/kernel/src/filesystem/rootfs/inode.cpp +++ b/kernel/src/filesystem/rootfs/inode.cpp @@ -5,10 +5,7 @@ #include <kstd/memory> #include <kstd/string> -#include <algorithm> #include <cstddef> -#include <string_view> -#include <utility> namespace kernel::filesystem::rootfs { @@ -22,17 +19,6 @@ namespace kernel::filesystem::rootfs return 0; } - auto inode::add_child(std::string_view name) -> void - { - m_children.push_back(std::make_pair(kstd::string{name}, kstd::make_shared<inode>())); - } - - auto inode::lookup_child(std::string_view name) -> kstd::shared_ptr<inode> - { - auto it = std::ranges::find_if(m_children, [&](auto const & pair) { return pair.first == name; }); - return (it != m_children.end()) ? it->second : nullptr; - } - auto inode::is_directory() const -> bool { return true; diff --git a/kernel/src/filesystem/rootfs/inode.tests.cpp b/kernel/src/filesystem/rootfs/inode.tests.cpp index 7cc217f..f4b634f 100644 --- a/kernel/src/filesystem/rootfs/inode.tests.cpp +++ b/kernel/src/filesystem/rootfs/inode.tests.cpp @@ -6,53 +6,6 @@ #include <catch2/catch_test_macros.hpp> -SCENARIO("Rootfs inode creation", "[filesystem][rootfs][inode]") -{ - GIVEN("a rootfs inode") - { - auto inode = kernel::filesystem::rootfs::inode{}; - - THEN("the inode has the correct kind") - { - REQUIRE(inode.is_directory()); - REQUIRE_FALSE(inode.is_device()); - REQUIRE_FALSE(inode.is_regular()); - REQUIRE_FALSE(inode.is_symbolic_link()); - } - - THEN("the inode has no children") - { - REQUIRE(inode.lookup_child("child") == nullptr); - } - } -} - -SCENARIO("Rootfs inode child management", "[filesystem][rootfs][inode]") -{ - GIVEN("a rootfs inode") - { - auto inode = kernel::filesystem::rootfs::inode{}; - - WHEN("adding a child inode") - { - inode.add_child("child"); - inode.add_child("another child"); - - THEN("the child can be looked up by name") - { - auto child_inode = inode.lookup_child("child"); - REQUIRE(child_inode != nullptr); - REQUIRE(child_inode->is_directory()); - } - - THEN("looking up a non-existent child returns null") - { - REQUIRE(inode.lookup_child("nonexistent") == nullptr); - } - } - } -} - SCENARIO("Rootfs inode read/write", "[filesystem][rootfs][inode]") { GIVEN("a rootfs inode") diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index f5d57be..8636d0f 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -20,6 +20,7 @@ #include <optional> #include <ranges> #include <string_view> +#include <utility> namespace { @@ -46,20 +47,13 @@ namespace kernel::filesystem root_fs->mount(nullptr); auto root_fs_root_dentry = kstd::make_shared<dentry>(nullptr, root_fs->root_inode(), "/"); - m_mount_table.add_mount(kstd::make_shared<mount>(nullptr, root_fs_root_dentry, root_fs, nullptr)); + auto root_mount = kstd::make_shared<mount>(nullptr, root_fs_root_dentry, root_fs, nullptr); + m_mount_table.add_mount(root_mount); // mount devfs at /dev (inside rootfs, temporary, will be shadowed) auto device_fs = kstd::make_shared<devfs::filesystem>(); device_fs->mount(nullptr); - - if (auto dev_mount_point_dentry = resolve_path("/dev")) - { - do_mount_internal(dev_mount_point_dentry, device_fs); - } - else - { - kapi::system::panic("[FILESYSTEM] failed to resolve /dev for initial devfs mount."); - } + graft_persistent_device_fs(device_fs); // mount boot fs at / (shadows rootfs), re-graft devfs if (auto boot_device_dentry = resolve_path("/dev/ram0")) @@ -68,7 +62,7 @@ namespace kernel::filesystem { if (auto root_dentry = resolve_path("/")) { - do_mount_internal(root_dentry, boot_root_fs); + do_mount_internal(root_dentry, root_mount, boot_root_fs); graft_persistent_device_fs(device_fs); } } @@ -87,7 +81,26 @@ namespace kernel::filesystem auto vfs::open(std::string_view path) -> kstd::shared_ptr<dentry> { - return resolve_path(path); + auto [dentry, mount] = resolve_path_internal(path); + if (!dentry || !mount) + { + return nullptr; + } + mount->increment_ref_count(); + return dentry; + } + + auto vfs::close(std::string_view path) -> operation_result + { + if (auto mount = find_mount(path)) + { + if (mount->decrement_ref_count()) + { + return operation_result::success; + } + return operation_result::close_failed; + } + return operation_result::invalid_path; } auto vfs::do_mount(std::string_view source, std::string_view target) -> operation_result @@ -97,13 +110,15 @@ namespace kernel::filesystem return operation_result::invalid_path; } - if (auto mount_point_dentry = resolve_path(target)) + auto [mount_point_dentry, mount_context] = resolve_path_internal(target); + + if (mount_point_dentry && mount_context) { if (auto source_dentry = resolve_path(source)) { if (auto fs = kernel::filesystem::filesystem::probe_and_mount(source_dentry->get_inode())) { - do_mount_internal(mount_point_dentry, fs); + do_mount_internal(mount_point_dentry, mount_context, fs); return operation_result::success; } return operation_result::invalid_filesystem; @@ -125,25 +140,18 @@ namespace kernel::filesystem { return operation_result::success; } - - if (remove_result == mount_table::operation_result::has_child_mounts) + else if (remove_result == mount_table::operation_result::mount_not_found) { - return operation_result::unmount_failed; + return operation_result::mount_point_not_found; } - return operation_result::mount_point_not_found; + return operation_result::unmount_failed; } auto vfs::do_mount_internal(kstd::shared_ptr<dentry> const & mount_point_dentry, - kstd::shared_ptr<filesystem> const & fs) -> void + kstd::shared_ptr<mount> const & parent_mount, kstd::shared_ptr<filesystem> const & fs) + -> void { - auto parent_mount_dentry = mount_point_dentry->find_mount_root_dentry(); - kstd::shared_ptr<mount> parent_mount = nullptr; - if (parent_mount_dentry) - { - parent_mount = m_mount_table.find_exact_mount(parent_mount_dentry->get_absolute_path().view()); - } - auto new_fs_root = kstd::make_shared<dentry>(mount_point_dentry->get_parent(), fs->root_inode(), mount_point_dentry->get_name()); auto new_mount = kstd::make_shared<mount>(mount_point_dentry, new_fs_root, fs, parent_mount); @@ -152,27 +160,28 @@ namespace kernel::filesystem auto vfs::graft_persistent_device_fs(kstd::shared_ptr<devfs::filesystem> const & device_fs) -> void { - if (auto new_root_dentry = resolve_path("/")) + auto [root_mount_point_dentry, root_mount] = resolve_path_internal("/"); + if (root_mount_point_dentry && root_mount) { - auto dev_dentry = new_root_dentry->find_child("dev"); + auto dev_dentry = root_mount_point_dentry->find_child("dev"); if (!dev_dentry) { - dev_dentry = kstd::make_shared<dentry>(new_root_dentry, device_fs->root_inode(), "dev"); - new_root_dentry->add_child(dev_dentry); + dev_dentry = kstd::make_shared<dentry>(root_mount_point_dentry, device_fs->root_inode(), "dev"); + root_mount_point_dentry->add_child(dev_dentry); } - do_mount_internal(dev_dentry, device_fs); + do_mount_internal(dev_dentry, root_mount, device_fs); } } - auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr<dentry> + auto vfs::resolve_path_internal(std::string_view path) -> std::pair<kstd::shared_ptr<dentry>, kstd::shared_ptr<mount>> { if (!path::is_valid_absolute_path(path)) { - return nullptr; + return {nullptr, nullptr}; } - auto current_mount = m_mount_table.find_exact_mount("/"); + auto current_mount = m_mount_table.find_mount("/"); if (!current_mount) { kapi::system::panic("[FILESYSTEM] no root mount found."); @@ -225,7 +234,7 @@ namespace kernel::filesystem auto found_inode = current_fs->lookup(current_dentry->get_inode(), part.view()); if (!found_inode) { - return nullptr; + return {nullptr, nullptr}; } next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part.view()); @@ -233,7 +242,7 @@ namespace kernel::filesystem } else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point)) { - current_mount = m_mount_table.find_exact_mount(next_dentry->get_absolute_path().view()); + current_mount = m_mount_table.find_mount(next_dentry->get_absolute_path().view()); if (!current_mount) { kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found."); @@ -246,7 +255,7 @@ namespace kernel::filesystem { if (symlink_counter++ > constants::symloop_max) { - return nullptr; + return {nullptr, nullptr}; } kstd::vector<uint8_t> buffer(constants::symlink_max_path_length); @@ -261,7 +270,7 @@ namespace kernel::filesystem if (path::is_valid_absolute_path(symbolic_link_path)) { - current_mount = m_mount_table.find_exact_mount("/"); + current_mount = m_mount_table.find_mount("/"); current_dentry = current_mount->get_root_dentry(); } continue; @@ -269,9 +278,19 @@ namespace kernel::filesystem current_dentry = next_dentry; } + return {current_dentry, current_mount}; + } - return current_dentry; + auto vfs::resolve_path(std::string_view path) -> kstd::shared_ptr<dentry> + { + return resolve_path_internal(path).first; } + + auto vfs::find_mount(std::string_view path) -> kstd::shared_ptr<mount> + { + return resolve_path_internal(path).second; + } + } // namespace kernel::filesystem namespace kernel::tests::filesystem::vfs diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp index 0f1d6d5..648ebb8 100644 --- a/kernel/src/filesystem/vfs.tests.cpp +++ b/kernel/src/filesystem/vfs.tests.cpp @@ -105,6 +105,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); REQUIRE(mounted_monkey_1 != nullptr); + REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); @@ -126,12 +128,47 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(mounted_monkey_1 != nullptr); REQUIRE(mounted_fish1 != nullptr); + REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(mounted_fish1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); } + THEN("image can be mounted, unmount only if no files are open") + { + REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); + + auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt"); + REQUIRE(mounted_monkey_1 != nullptr); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); + + REQUIRE(vfs.close(mounted_monkey_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); + } + + THEN("file with invalid path or not opened file cannot be closed") + { + REQUIRE(vfs.close("invalid_path") == kernel::filesystem::vfs::operation_result::invalid_path); + REQUIRE(vfs.close("/information/info_1.txt") == kernel::filesystem::vfs::operation_result::close_failed); + } + + THEN("file cannot be closed twice") + { + auto info_1 = vfs.open("/information/info_1.txt"); + REQUIRE(info_1 != nullptr); + + REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::close_failed); + } + THEN("images can be stacked mounted and correct file system is unmounted again") { REQUIRE(vfs.do_mount("/dev/ram16", "/information") == kernel::filesystem::vfs::operation_result::success); @@ -140,6 +177,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets != nullptr); + REQUIRE(vfs.close(mounted_tickets->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); mounted_tickets = vfs.open("/information/entrance/tickets.txt"); REQUIRE(mounted_tickets == nullptr); @@ -161,6 +201,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); + REQUIRE(vfs.close(water->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); info_1 = vfs.open("/information/info_1.txt"); @@ -180,6 +222,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto water = vfs.open("/monkey_house/infrastructure/water.txt"); REQUIRE(water != nullptr); + REQUIRE(vfs.close(water->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + auto dev_ram_16 = vfs.open("/dev/ram16"); REQUIRE(dev_ram_16 == nullptr); @@ -196,6 +240,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto info_1 = vfs.open("/information/info_1.txt"); REQUIRE(info_1 != nullptr); + REQUIRE(vfs.close(info_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success); REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success); @@ -310,13 +356,15 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto dentry = vfs.open("/information/sheep_1.txt"); REQUIRE(dentry != nullptr); - auto sheep_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry->get_inode()); + auto sheep_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(dentry); kstd::vector<std::byte> buffer(7); auto bytes_read = sheep_1_ofd->read(buffer.data(), buffer.size()); std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "sheep_1"); + REQUIRE(vfs.close(dentry->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(unmounted_sheep_1 == nullptr); @@ -335,8 +383,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS REQUIRE(sheep_1 != nullptr); REQUIRE(goat_1 != nullptr); - auto sheep_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(sheep_1->get_inode()); - auto goat_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(goat_1->get_inode()); + auto sheep_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(sheep_1); + auto goat_1_ofd = kstd::make_shared<kernel::filesystem::open_file_descriptor>(goat_1); kstd::vector<std::byte> sheep_buffer(7); auto bytes_read = sheep_1_ofd->read(sheep_buffer.data(), sheep_buffer.size()); @@ -348,6 +396,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS buffer_as_str = std::string_view{reinterpret_cast<char *>(goat_buffer.data()), bytes_read}; REQUIRE(buffer_as_str == "goat_1"); + REQUIRE(vfs.close(sheep_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.close(goat_1->get_absolute_path().view()) == kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed); REQUIRE(vfs.unmount("/information/stable") == kernel::filesystem::vfs::operation_result::success); @@ -357,6 +408,9 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(still_mounted_sheep_1 != nullptr); + REQUIRE(vfs.close(still_mounted_sheep_1->get_absolute_path().view()) == + kernel::filesystem::vfs::operation_result::success); + REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success); auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt"); REQUIRE(unmounted_sheep_1 == nullptr); |
