diff options
| author | Lukas Oesch <lukasoesch20@gmail.com> | 2026-05-15 16:50:55 +0200 |
|---|---|---|
| committer | Lukas Oesch <lukasoesch20@gmail.com> | 2026-05-16 11:56:07 +0200 |
| commit | 1d647adb1ba20121eeb5c8e4470f48b2e972b3d4 (patch) | |
| tree | d74522980f1853a6be0628158534c29cf48bdb1c /kernel | |
| parent | 95ff59017db74a6988f791ca9f122254dd743541 (diff) | |
| download | kernel-1d647adb1ba20121eeb5c8e4470f48b2e972b3d4.tar.xz kernel-1d647adb1ba20121eeb5c8e4470f48b2e972b3d4.zip | |
Mount can only be unmounted if no references are present, increment references on open file and decrement on close file
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/include/kernel/filesystem/mount.hpp | 19 | ||||
| -rw-r--r-- | kernel/include/kernel/filesystem/mount_table.hpp | 3 | ||||
| -rw-r--r-- | kernel/include/kernel/filesystem/open_file_descriptor.hpp | 8 | ||||
| -rw-r--r-- | kernel/include/kernel/filesystem/vfs.hpp | 8 | ||||
| -rw-r--r-- | kernel/kapi/filesystem.cpp | 10 | ||||
| -rw-r--r-- | kernel/src/filesystem/mount.cpp | 22 | ||||
| -rw-r--r-- | kernel/src/filesystem/mount_table.cpp | 5 | ||||
| -rw-r--r-- | kernel/src/filesystem/open_file_descriptor.cpp | 7 | ||||
| -rw-r--r-- | kernel/src/filesystem/open_file_descriptor.tests.cpp | 24 | ||||
| -rw-r--r-- | kernel/src/filesystem/vfs.cpp | 17 |
10 files changed, 104 insertions, 19 deletions
diff --git a/kernel/include/kernel/filesystem/mount.hpp b/kernel/include/kernel/filesystem/mount.hpp index f920891..fb5a627 100644 --- a/kernel/include/kernel/filesystem/mount.hpp +++ b/kernel/include/kernel/filesystem/mount.hpp @@ -54,12 +54,29 @@ 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; + 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 742c928..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 }; /** diff --git a/kernel/include/kernel/filesystem/open_file_descriptor.hpp b/kernel/include/kernel/filesystem/open_file_descriptor.hpp index 823fe13..7ca7350 100644 --- a/kernel/include/kernel/filesystem/open_file_descriptor.hpp +++ b/kernel/include/kernel/filesystem/open_file_descriptor.hpp @@ -50,7 +50,13 @@ 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<dentry> m_dentry; diff --git a/kernel/include/kernel/filesystem/vfs.hpp b/kernel/include/kernel/filesystem/vfs.hpp index 7e2eae7..48b99b2 100644 --- a/kernel/include/kernel/filesystem/vfs.hpp +++ b/kernel/include/kernel/filesystem/vfs.hpp @@ -33,6 +33,7 @@ namespace kernel::filesystem mount_point_not_found = -3, unmount_failed = -4, invalid_filesystem = -5, + close_failed = -6 }; /** @@ -61,6 +62,13 @@ namespace kernel::filesystem auto open(std::string_view path) -> kstd::shared_ptr<dentry>; /** + @brief Close a file by its associated @p dentry. + @param dentry The dentry of the file to close. + @return The result of the close operation. + */ + auto close(kstd::shared_ptr<dentry> const & dentry) -> 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. diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp index 77d7eb0..1782da5 100644 --- a/kernel/kapi/filesystem.cpp +++ b/kernel/kapi/filesystem.cpp @@ -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()) == + 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/src/filesystem/mount.cpp b/kernel/src/filesystem/mount.cpp index 749c86a..3016509 100644 --- a/kernel/src/filesystem/mount.cpp +++ b/kernel/src/filesystem/mount.cpp @@ -18,6 +18,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 +54,25 @@ 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; + } } // namespace kernel::filesystem
\ No newline at end of file diff --git a/kernel/src/filesystem/mount_table.cpp b/kernel/src/filesystem/mount_table.cpp index b582fd9..9951590 100644 --- a/kernel/src/filesystem/mount_table.cpp +++ b/kernel/src/filesystem/mount_table.cpp @@ -30,7 +30,6 @@ namespace kernel::filesystem auto mount_table::remove_mount(std::string_view path) -> operation_result { - // TODO BA-FS26 check wheter something is open in this mount auto mount_it = find_mount_iterator(path); if (mount_it == m_mounts.end()) { @@ -38,6 +37,10 @@ namespace kernel::filesystem } 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; diff --git a/kernel/src/filesystem/open_file_descriptor.cpp b/kernel/src/filesystem/open_file_descriptor.cpp index 27e6449..ebaabef 100644 --- a/kernel/src/filesystem/open_file_descriptor.cpp +++ b/kernel/src/filesystem/open_file_descriptor.cpp @@ -33,9 +33,14 @@ namespace kernel::filesystem 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 8c24cf0..1910b8b 100644 --- a/kernel/src/filesystem/open_file_descriptor.tests.cpp +++ b/kernel/src/filesystem/open_file_descriptor.tests.cpp @@ -26,7 +26,7 @@ SCENARIO("Open file descriptor construction", "[filesystem][open_file_descriptor THEN("the initial offset is zero") { - REQUIRE(file_descriptor.offset() == 0); + REQUIRE(file_descriptor.get_offset() == 0); } } } @@ -42,29 +42,29 @@ SCENARIO("Open file descriptor read/write offset management", "[filesystem][open 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); } } } @@ -89,7 +89,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Ope 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"); @@ -100,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/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 77ae015..3b3d6ff 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -89,7 +89,22 @@ 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); + mount->increment_ref_count(); + return dentry; + } + + auto vfs::close(kstd::shared_ptr<dentry> const & dentry) -> operation_result + { + if (auto mount = find_mount(dentry->get_absolute_path().view())) + { + 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 |
