aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/include/kernel/filesystem/mount.hpp19
-rw-r--r--kernel/include/kernel/filesystem/mount_table.hpp3
-rw-r--r--kernel/include/kernel/filesystem/open_file_descriptor.hpp8
-rw-r--r--kernel/include/kernel/filesystem/vfs.hpp8
-rw-r--r--kernel/kapi/filesystem.cpp10
-rw-r--r--kernel/src/filesystem/mount.cpp22
-rw-r--r--kernel/src/filesystem/mount_table.cpp5
-rw-r--r--kernel/src/filesystem/open_file_descriptor.cpp7
-rw-r--r--kernel/src/filesystem/open_file_descriptor.tests.cpp24
-rw-r--r--kernel/src/filesystem/vfs.cpp17
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