aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kernel/main.cpp2
-rw-r--r--kernel/kernel/vfs.cpp10
-rw-r--r--kernel/kernel/vfs.hpp14
-rw-r--r--kernel/kernel/vfs/directory_file_descriptor.cpp80
-rw-r--r--kernel/kernel/vfs/mount_table.cpp17
-rw-r--r--kernel/kernel/vfs/mount_table.hpp13
6 files changed, 134 insertions, 2 deletions
diff --git a/kernel/kernel/main.cpp b/kernel/kernel/main.cpp
index 52562ad7..7083d517 100644
--- a/kernel/kernel/main.cpp
+++ b/kernel/kernel/main.cpp
@@ -227,7 +227,7 @@ auto run_demo() -> void
auto stat = kapi::filesystem::status(kstd::format("{}/{}", path, entry.name));
if (stat)
{
- kstd::println("\t{:<8} {:<#8o} {:>#8} {:>3}:{<3} {}", stat->inode_number, stat->mode, stat->size,
+ kstd::println("\t{:<8} {:<#8o} {:>#8} {:>3}:{<3} {}", entry.inode_number, stat->mode, stat->size,
stat->raw_device.major, stat->raw_device.minor, entry.name);
}
else
diff --git a/kernel/kernel/vfs.cpp b/kernel/kernel/vfs.cpp
index 742af328..42e98219 100644
--- a/kernel/kernel/vfs.cpp
+++ b/kernel/kernel/vfs.cpp
@@ -279,6 +279,16 @@ namespace kernel::vfs
return kstd::failure(errc::invalid_argument);
}
+ auto vfs::houses_mounts(kstd::shared_ptr<dentry> parent) const -> bool
+ {
+ return m_mount_table.houses_mounts(parent);
+ }
+
+ auto vfs::find_mount_at(kstd::shared_ptr<dentry> parent, std::string_view name) -> kstd::shared_ptr<struct mount>
+ {
+ return m_mount_table.find_mount_at(parent, name);
+ }
+
auto vfs::create_inode(std::string_view path, kapi::filesystem::file_type type,
std::optional<kapi::filesystem::device_number> raw_device) -> kstd::result<void>
{
diff --git a/kernel/kernel/vfs.hpp b/kernel/kernel/vfs.hpp
index 4528ab2e..a722a48d 100644
--- a/kernel/kernel/vfs.hpp
+++ b/kernel/kernel/vfs.hpp
@@ -109,6 +109,20 @@ namespace kernel::vfs
auto create_device_node(std::string_view path, std::uint32_t mode, kapi::filesystem::device_number device)
-> kstd::result<void>;
+ //! Check if a given given dentry houses any mounts.
+ //!
+ //! @param parent The suspected mount parent.
+ //! @return @c true iff. there is directory below the dentry that is a mount point, @c false otherwise.
+ [[nodiscard]] auto houses_mounts(kstd::shared_ptr<dentry> parent) const -> bool;
+
+ //! Find the mount associated with a given directory in a given parent.
+ //!
+ //! @param parent The suspected parent of the suspected mount point.
+ //! @param name The name of the mount point.
+ //! @return The mount if it exists, nullptr otherwise.
+ [[nodiscard]] auto find_mount_at(kstd::shared_ptr<dentry> parent, std::string_view name)
+ -> kstd::shared_ptr<struct mount>;
+
private:
// 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
diff --git a/kernel/kernel/vfs/directory_file_descriptor.cpp b/kernel/kernel/vfs/directory_file_descriptor.cpp
index c1fb2a55..54785f81 100644
--- a/kernel/kernel/vfs/directory_file_descriptor.cpp
+++ b/kernel/kernel/vfs/directory_file_descriptor.cpp
@@ -1,18 +1,89 @@
#include <kernel/vfs/directory_file_descriptor.hpp>
-#include <kernel/vfs/dentry.hpp>
+#include <kernel/vfs.hpp>
#include <kapi/filesystem.hpp>
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
+#include <algorithm>
#include <cstddef>
+#include <ranges>
#include <span>
namespace kernel::vfs
{
+ namespace
+ {
+
+ auto fixup_dot_dot(std::span<kapi::filesystem::directory_entry> entries,
+ kstd::shared_ptr<dentry> const & current_directory) -> void
+ {
+ auto state = current_directory->inode()->driver_state().lock();
+ if (!state)
+ {
+ return;
+ }
+
+ auto mount = state->owner().lock();
+ if (!mount || mount->root_dentry() != current_directory || mount->mount_path() == "/")
+ {
+ return;
+ }
+
+ auto parent = mount->mount_dentry()->parent();
+ if (!parent)
+ {
+ return;
+ }
+
+ auto parent_status = parent->inode()->status();
+ if (!parent_status)
+ {
+ return;
+ }
+
+ auto found = std::ranges::find(entries, "..", &kapi::filesystem::directory_entry::name);
+ if (found != std::ranges::end(entries))
+ {
+ found->inode_number = parent_status->inode_number;
+ }
+ }
+
+ auto fixup_mounts(std::span<kapi::filesystem::directory_entry> entries,
+ kstd::shared_ptr<dentry> const & current_directory) -> void
+ {
+ auto directories = std::views::filter(
+ entries, [](auto const & entry) { return entry.type == kapi::filesystem::file_type::directory; });
+
+ auto & vfs_instance = vfs::vfs::get();
+
+ if (!vfs_instance.houses_mounts(current_directory))
+ {
+ return;
+ }
+
+ std::ranges::for_each(directories, [&](auto & entry) {
+ auto mounted = vfs_instance.find_mount_at(current_directory, entry.name);
+ if (!mounted)
+ {
+ return;
+ }
+
+ auto mount_root_status = mounted->root_dentry()->inode()->status();
+ if (!mount_root_status)
+ {
+ return;
+ }
+
+ entry.inode_number = mount_root_status->inode_number;
+ });
+ }
+
+ } // namespace
+
auto directory_file_descriptor::read_directory(std::span<kapi::filesystem::directory_entry> entries)
-> kstd::result<std::size_t>
{
@@ -23,6 +94,13 @@ namespace kernel::vfs
}
m_position = result->second;
+ auto const count = result->first;
+
+ auto valid_entries = entries.first(count);
+
+ fixup_dot_dot(valid_entries, get_dentry());
+ fixup_mounts(valid_entries, get_dentry());
+
return result->first;
}
diff --git a/kernel/kernel/vfs/mount_table.cpp b/kernel/kernel/vfs/mount_table.cpp
index 43dff516..c7198396 100644
--- a/kernel/kernel/vfs/mount_table.cpp
+++ b/kernel/kernel/vfs/mount_table.cpp
@@ -83,6 +83,23 @@ namespace kernel::vfs
return (mount_it != m_mounts.end()) ? *mount_it : nullptr;
}
+ auto mount_table::houses_mounts(kstd::shared_ptr<dentry> parent) const -> bool
+ {
+ return std::ranges::any_of(m_mounts, [&](auto const & mount) {
+ auto const dentry = mount->mount_dentry();
+ return dentry && dentry->parent() == parent;
+ });
+ }
+
+ auto mount_table::find_mount_at(kstd::shared_ptr<dentry> parent, std::string_view name) -> kstd::shared_ptr<mount>
+ {
+ auto found = std::ranges::find_last_if(m_mounts, [&](auto const & mount) {
+ auto const & dentry = mount->mount_dentry();
+ return dentry && dentry->parent() == parent && dentry->name() == name;
+ });
+ return found.begin() != std::ranges::end(m_mounts) ? *found.begin() : nullptr;
+ }
+
auto mount_table::move_mount(kstd::shared_ptr<mount> const & mount, kstd::shared_ptr<dentry> const & mount_point,
kstd::shared_ptr<struct mount> const & parent) -> void
{
diff --git a/kernel/kernel/vfs/mount_table.hpp b/kernel/kernel/vfs/mount_table.hpp
index d2bb2f94..afeaf5eb 100644
--- a/kernel/kernel/vfs/mount_table.hpp
+++ b/kernel/kernel/vfs/mount_table.hpp
@@ -38,6 +38,19 @@ namespace kernel::vfs
//! @return A pointer to the mount with the exact matching path on success, nullpointer otherwise.
[[nodiscard]] auto find_mount(std::string_view path) const -> kstd::shared_ptr<mount>;
+ //! Check if a given given dentry houses any mounts.
+ //!
+ //! @param parent The suspected mount parent.
+ //! @return @c true iff. there is directory below the dentry that is a mount point, @c false otherwise.
+ [[nodiscard]] auto houses_mounts(kstd::shared_ptr<dentry> parent) const -> bool;
+
+ //! Find the mount associated with a given directory in a given parent.
+ //!
+ //! @param parent The suspected parent of the suspected mount point.
+ //! @param name The name of the mount point.
+ //! @return The mount if it exists, nullptr otherwise.
+ [[nodiscard]] auto find_mount_at(kstd::shared_ptr<dentry> parent, std::string_view name) -> kstd::shared_ptr<mount>;
+
//! Move the mount attachment of an existing mount
//!
//! @param mount The mount to modify.