1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-30 17:28:10 +00:00

Kernel/FileSystem: Send proper filetypes when traversing RAM-backed FSes

SysFS, ProcFS and DevPtsFS were all sending filetype 0 when traversing
their directories, but it is actually very easy to send proper filetypes
in these filesystems.
This patch binds all RAM backed filesystems to use only one enum for
their internal filetype, to simplify the implementation and allow
sharing of code.
Please note that the Plan9FS case is currently not solved as I am not
familiar with this filesystem and its constructs.

The ProcFS mostly keeps track of the filetype, and a fix was needed for
the /proc root directory - all processes exhibit a directory inside it
which makes it very easy to hardcode the directory filetype for them.
There's also the `self` symlink inode which is now exposed as DT_LNK.

As for SysFS, we could leverage the fact everything inherits from the
SysFSComponent class, so we could have a virtual const method to return
the proper filetype.
Most of the files in SysFS are "regular" files though, so the base class
has a non-pure virtual method.

Lastly, the DevPtsFS simply hardcodes '.' and '..' as directory file
type, and everything else is hardcoded to send the character device file
type, as this filesystem is only exposing character pts device files.
This commit is contained in:
Liav A 2024-01-05 11:18:02 +02:00 committed by Andrew Kaster
parent 75bd1308c5
commit a10e63f08e
16 changed files with 169 additions and 111 deletions

View file

@ -8,45 +8,46 @@
#include <AK/StringView.h>
#include <AK/Types.h>
#include <Kernel/FileSystem/RAMBackedFileType.h>
namespace Kernel {
struct segmented_global_inode_index {
StringView name;
u8 file_type;
RAMBackedFileType file_type;
u32 primary;
u16 subdirectory;
u32 property;
};
constexpr segmented_global_inode_index global_inode_ids[] = {
{ "."sv, DT_DIR, 0, 0, 1 }, // NOTE: This is here for the root directory
{ "self"sv, DT_DIR, 0, 0, 2 }
{ "."sv, RAMBackedFileType::Directory, 0, 0, 1 }, // NOTE: This is here for the root directory
{ "self"sv, RAMBackedFileType::Directory, 0, 0, 2 }
};
struct segmented_process_directory_entry {
StringView name;
u8 file_type;
RAMBackedFileType file_type;
u16 subdirectory;
u32 property;
};
constexpr segmented_process_directory_entry main_process_directory_root_entry = { "."sv, DT_DIR, 0, 0 };
constexpr segmented_process_directory_entry process_fd_subdirectory_root_entry = { "."sv, DT_DIR, 1, 0 };
constexpr segmented_process_directory_entry process_stacks_subdirectory_root_entry = { "."sv, DT_DIR, 2, 0 };
constexpr segmented_process_directory_entry process_children_subdirectory_root_entry = { "."sv, DT_DIR, 3, 0 };
constexpr segmented_process_directory_entry main_process_directory_root_entry = { "."sv, RAMBackedFileType::Directory, 0, 0 };
constexpr segmented_process_directory_entry process_fd_subdirectory_root_entry = { "."sv, RAMBackedFileType::Directory, 1, 0 };
constexpr segmented_process_directory_entry process_stacks_subdirectory_root_entry = { "."sv, RAMBackedFileType::Directory, 2, 0 };
constexpr segmented_process_directory_entry process_children_subdirectory_root_entry = { "."sv, RAMBackedFileType::Directory, 3, 0 };
constexpr segmented_process_directory_entry process_fd_directory_entry = { "fd"sv, DT_DIR, 1, 0 };
constexpr segmented_process_directory_entry process_stacks_directory_entry = { "stacks"sv, DT_DIR, 2, 0 };
constexpr segmented_process_directory_entry process_children_directory_entry = { "children"sv, DT_DIR, 3, 0 };
constexpr segmented_process_directory_entry process_unveil_list_entry = { "unveil"sv, DT_REG, 0, 1 };
constexpr segmented_process_directory_entry process_pledge_list_entry = { "pledge"sv, DT_REG, 0, 2 };
constexpr segmented_process_directory_entry process_fds_list_entry = { "fds"sv, DT_REG, 0, 3 };
constexpr segmented_process_directory_entry process_exe_symlink_entry = { "exe"sv, DT_LNK, 0, 4 };
constexpr segmented_process_directory_entry process_cwd_symlink_entry = { "cwd"sv, DT_LNK, 0, 5 };
constexpr segmented_process_directory_entry process_perf_events_entry = { "perf_events"sv, DT_REG, 0, 6 };
constexpr segmented_process_directory_entry process_vm_entry = { "vm"sv, DT_REG, 0, 7 };
constexpr segmented_process_directory_entry process_cmdline_entry = { "cmdline"sv, DT_REG, 0, 8 };
constexpr segmented_process_directory_entry process_fd_directory_entry = { "fd"sv, RAMBackedFileType::Directory, 1, 0 };
constexpr segmented_process_directory_entry process_stacks_directory_entry = { "stacks"sv, RAMBackedFileType::Directory, 2, 0 };
constexpr segmented_process_directory_entry process_children_directory_entry = { "children"sv, RAMBackedFileType::Directory, 3, 0 };
constexpr segmented_process_directory_entry process_unveil_list_entry = { "unveil"sv, RAMBackedFileType::Regular, 0, 1 };
constexpr segmented_process_directory_entry process_pledge_list_entry = { "pledge"sv, RAMBackedFileType::Regular, 0, 2 };
constexpr segmented_process_directory_entry process_fds_list_entry = { "fds"sv, RAMBackedFileType::Regular, 0, 3 };
constexpr segmented_process_directory_entry process_exe_symlink_entry = { "exe"sv, RAMBackedFileType::Link, 0, 4 };
constexpr segmented_process_directory_entry process_cwd_symlink_entry = { "cwd"sv, RAMBackedFileType::Link, 0, 5 };
constexpr segmented_process_directory_entry process_perf_events_entry = { "perf_events"sv, RAMBackedFileType::Regular, 0, 6 };
constexpr segmented_process_directory_entry process_vm_entry = { "vm"sv, RAMBackedFileType::Regular, 0, 7 };
constexpr segmented_process_directory_entry process_cmdline_entry = { "cmdline"sv, RAMBackedFileType::Regular, 0, 8 };
constexpr segmented_process_directory_entry main_process_directory_entries[] = {
process_fd_directory_entry,
process_stacks_directory_entry,

View file

@ -8,6 +8,7 @@
#include <Kernel/FileSystem/ProcFS/FileSystem.h>
#include <Kernel/FileSystem/ProcFS/Inode.h>
#include <Kernel/FileSystem/RAMBackedFileType.h>
namespace Kernel {
@ -32,6 +33,11 @@ ErrorOr<void> ProcFS::initialize()
return {};
}
u8 ProcFS::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const
{
return ram_backed_file_type_to_directory_entry_type(entry);
}
Inode& ProcFS::root_inode()
{
return *m_root_inode;

View file

@ -28,6 +28,8 @@ public:
virtual Inode& root_inode() override;
private:
virtual u8 internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const override;
ProcFS();
ErrorOr<NonnullRefPtr<Inode>> get_inode(InodeIdentifier) const;

View file

@ -1,12 +1,13 @@
/*
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
* Copyright (c) 2021-2023, Liav A. <liavalb@hotmail.co.il>
* Copyright (c) 2021-2024, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/FileSystem/ProcFS/Inode.h>
#include <Kernel/FileSystem/RAMBackedFileType.h>
#include <Kernel/Tasks/Process.h>
#include <Kernel/Time/TimeManagement.h>
@ -108,16 +109,16 @@ ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, InodeIndex inode_index)
ErrorOr<void> ProcFSInode::traverse_as_root_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
TRY(callback({ "."sv, { fsid(), 1 }, 0 }));
TRY(callback({ ".."sv, { fsid(), 0 }, 0 }));
TRY(callback({ "self"sv, { fsid(), 2 }, 0 }));
TRY(callback({ "."sv, { fsid(), to_underlying(RAMBackedFileType::Directory) }, 0 }));
TRY(callback({ ".."sv, { fsid(), to_underlying(RAMBackedFileType::Directory) }, 0 }));
TRY(callback({ "self"sv, { fsid(), 2 }, to_underlying(RAMBackedFileType::Link) }));
return Process::for_each_in_same_jail([&](Process& process) -> ErrorOr<void> {
VERIFY(!(process.pid() < 0));
u64 process_id = (u64)process.pid().value();
InodeIdentifier identifier = { fsid(), static_cast<InodeIndex>(process_id << 36) };
auto process_id_string = TRY(KString::formatted("{:d}", process_id));
TRY(callback({ process_id_string->view(), identifier, 0 }));
TRY(callback({ process_id_string->view(), identifier, to_underlying(RAMBackedFileType::Directory) }));
return {};
});
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2023, Liav A. <liavalb@hotmail.co.il>
* Copyright (c) 2021-2024, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -9,6 +9,7 @@
#include <Kernel/Devices/TTY/TTY.h>
#include <Kernel/FileSystem/Custody.h>
#include <Kernel/FileSystem/ProcFS/Inode.h>
#include <Kernel/FileSystem/RAMBackedFileType.h>
#include <Kernel/Interrupts/InterruptDisabler.h>
#include <Kernel/Library/KBufferBuilder.h>
#include <Kernel/Memory/AnonymousVMObject.h>
@ -19,11 +20,11 @@ namespace Kernel {
ErrorOr<void> Process::traverse_as_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
TRY(callback({ main_process_directory_root_entry.name, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, main_process_directory_root_entry.file_type }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_global_directory_entry(global_inode_ids[0]) }, global_inode_ids[0].file_type }));
TRY(callback({ main_process_directory_root_entry.name, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, to_underlying(main_process_directory_root_entry.file_type) }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_global_directory_entry(global_inode_ids[0]) }, to_underlying(global_inode_ids[0].file_type) }));
for (auto& entry : main_process_directory_entries) {
TRY(callback({ entry.name, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), entry) }, entry.file_type }));
TRY(callback({ entry.name, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), entry) }, to_underlying(entry.file_type) }));
}
return {};
}
@ -62,16 +63,16 @@ ErrorOr<void> Process::procfs_get_thread_stack(ThreadID thread_id, KBufferBuilde
ErrorOr<void> Process::traverse_stacks_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
TRY(callback({ "."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), process_stacks_subdirectory_root_entry) }, DT_DIR }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, main_process_directory_root_entry.file_type }));
TRY(callback({ "."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), process_stacks_subdirectory_root_entry) }, to_underlying(RAMBackedFileType::Directory) }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, to_underlying(main_process_directory_root_entry.file_type) }));
return thread_list().with([&](auto& list) -> ErrorOr<void> {
for (auto const& thread : list) {
// NOTE: All property numbers should start from 1 as 0 is reserved for the directory itself.
auto entry = segmented_process_directory_entry { {}, DT_REG, process_stacks_subdirectory_root_entry.subdirectory, static_cast<u32>(thread.tid().value() + 1) };
auto entry = segmented_process_directory_entry { {}, RAMBackedFileType::Regular, process_stacks_subdirectory_root_entry.subdirectory, static_cast<u32>(thread.tid().value() + 1) };
InodeIdentifier identifier = { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), entry) };
auto name = TRY(KString::number(thread.tid().value()));
TRY(callback({ name->view(), identifier, 0 }));
TRY(callback({ name->view(), identifier, to_underlying(RAMBackedFileType::Regular) }));
}
return {};
});
@ -90,7 +91,7 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_stacks_directory(ProcFS& procfs, S
VERIFY(!(tid < 0));
if (needle == (unsigned)tid) {
// NOTE: All property numbers should start from 1 as 0 is reserved for the directory itself.
auto entry = segmented_process_directory_entry { {}, DT_REG, process_stacks_subdirectory_root_entry.subdirectory, static_cast<u32>(thread.tid().value() + 1) };
auto entry = segmented_process_directory_entry { {}, RAMBackedFileType::Regular, process_stacks_subdirectory_root_entry.subdirectory, static_cast<u32>(thread.tid().value() + 1) };
thread_stack_inode = procfs.get_inode({ procfs.fsid(), ProcFSInode::create_index_from_process_directory_entry(pid(), entry) });
return IterationDecision::Break;
}
@ -104,15 +105,15 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_stacks_directory(ProcFS& procfs, S
ErrorOr<void> Process::traverse_children_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
TRY(callback({ "."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), process_children_subdirectory_root_entry) }, DT_DIR }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, main_process_directory_root_entry.file_type }));
TRY(callback({ "."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), process_children_subdirectory_root_entry) }, to_underlying(RAMBackedFileType::Directory) }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, to_underlying(main_process_directory_root_entry.file_type) }));
return Process::for_each_in_same_jail([&](Process& process) -> ErrorOr<void> {
if (process.ppid() == pid()) {
auto name = TRY(KString::number(process.pid().value()));
// NOTE: All property numbers should start from 1 as 0 is reserved for the directory itself.
auto entry = segmented_process_directory_entry { {}, DT_LNK, process_children_subdirectory_root_entry.subdirectory, static_cast<u32>(process.pid().value() + 1) };
auto entry = segmented_process_directory_entry { {}, RAMBackedFileType::Link, process_children_subdirectory_root_entry.subdirectory, static_cast<u32>(process.pid().value() + 1) };
InodeIdentifier identifier = { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), entry) };
TRY(callback({ name->view(), identifier, DT_LNK }));
TRY(callback({ name->view(), identifier, to_underlying(RAMBackedFileType::Link) }));
}
return {};
});
@ -129,7 +130,7 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_children_directory(ProcFS& procfs,
return ENOENT;
// NOTE: All property numbers should start from 1 as 0 is reserved for the directory itself.
auto entry = segmented_process_directory_entry { {}, DT_LNK, process_children_subdirectory_root_entry.subdirectory, (maybe_pid.value() + 1) };
auto entry = segmented_process_directory_entry { {}, RAMBackedFileType::Link, process_children_subdirectory_root_entry.subdirectory, (maybe_pid.value() + 1) };
return procfs.get_inode({ procfs.fsid(), ProcFSInode::create_index_from_process_directory_entry(pid(), entry) });
}
@ -150,8 +151,8 @@ ErrorOr<size_t> Process::procfs_get_file_description_link(unsigned fd, KBufferBu
ErrorOr<void> Process::traverse_file_descriptions_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
TRY(callback({ "."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), process_fd_subdirectory_root_entry) }, DT_DIR }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, main_process_directory_root_entry.file_type }));
TRY(callback({ "."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), process_fd_subdirectory_root_entry) }, to_underlying(RAMBackedFileType::Directory) }));
TRY(callback({ ".."sv, { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), main_process_directory_root_entry) }, to_underlying(main_process_directory_root_entry.file_type) }));
u32 count = 0;
TRY(fds().with_shared([&](auto& fds) -> ErrorOr<void> {
return fds.try_enumerate([&](auto& file_description_metadata) -> ErrorOr<void> {
@ -161,9 +162,9 @@ ErrorOr<void> Process::traverse_file_descriptions_directory(FileSystemID fsid, F
}
auto name = TRY(KString::number(count));
// NOTE: All property numbers should start from 1 as 0 is reserved for the directory itself.
auto entry = segmented_process_directory_entry { {}, DT_LNK, process_fd_subdirectory_root_entry.subdirectory, count + 1 };
auto entry = segmented_process_directory_entry { {}, RAMBackedFileType::Link, process_fd_subdirectory_root_entry.subdirectory, count + 1 };
InodeIdentifier identifier = { fsid, ProcFSInode::create_index_from_process_directory_entry(pid(), entry) };
TRY(callback({ name->view(), identifier, DT_LNK }));
TRY(callback({ name->view(), identifier, to_underlying(RAMBackedFileType::Link) }));
count++;
return {};
});
@ -181,7 +182,7 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_file_descriptions_directory(ProcFS
return ENOENT;
// NOTE: All property numbers should start from 1 as 0 is reserved for the directory itself.
auto entry = segmented_process_directory_entry { {}, DT_LNK, process_fd_subdirectory_root_entry.subdirectory, (maybe_index.value() + 1) };
auto entry = segmented_process_directory_entry { {}, RAMBackedFileType::Link, process_fd_subdirectory_root_entry.subdirectory, (maybe_index.value() + 1) };
return procfs.get_inode({ procfs.fsid(), ProcFSInode::create_index_from_process_directory_entry(pid(), entry) });
}