mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
Kernel/FileSystem: Add the DevLoopFS filesystem
Similarly to DevPtsFS, this filesystem is about exposing loop device nodes easily in /dev/loop, so userspace doesn't need to do anything in order to use new devices immediately.
This commit is contained in:
parent
11ead5c84f
commit
0d2e4a7e67
Notes:
sideshowbarker
2024-07-17 09:49:33 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/0d2e4a7e67 Pull-request: https://github.com/SerenityOS/serenity/pull/23138 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/Hendiadyoin1 Reviewed-by: https://github.com/gmta
6 changed files with 292 additions and 0 deletions
|
@ -140,6 +140,8 @@ set(KERNEL_SOURCES
|
|||
FileSystem/AnonymousFile.cpp
|
||||
FileSystem/BlockBasedFileSystem.cpp
|
||||
FileSystem/Custody.cpp
|
||||
FileSystem/DevLoopFS/FileSystem.cpp
|
||||
FileSystem/DevLoopFS/Inode.cpp
|
||||
FileSystem/DevPtsFS/FileSystem.cpp
|
||||
FileSystem/DevPtsFS/Inode.cpp
|
||||
FileSystem/Ext2FS/FileSystem.cpp
|
||||
|
|
76
Kernel/FileSystem/DevLoopFS/FileSystem.cpp
Normal file
76
Kernel/FileSystem/DevLoopFS/FileSystem.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Devices/DeviceManagement.h>
|
||||
#include <Kernel/Devices/Loop/LoopDevice.h>
|
||||
#include <Kernel/FileSystem/DevLoopFS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/DevLoopFS/Inode.h>
|
||||
#include <Kernel/FileSystem/RAMBackedFileType.h>
|
||||
#include <Kernel/Time/TimeManagement.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullRefPtr<FileSystem>> DevLoopFS::try_create(ReadonlyBytes)
|
||||
{
|
||||
return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) DevLoopFS));
|
||||
}
|
||||
|
||||
DevLoopFS::DevLoopFS() = default;
|
||||
DevLoopFS::~DevLoopFS() = default;
|
||||
|
||||
u8 DevLoopFS::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const
|
||||
{
|
||||
return ram_backed_file_type_to_directory_entry_type(entry);
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFS::initialize()
|
||||
{
|
||||
m_root_inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) DevLoopFSInode(*this)));
|
||||
m_root_inode->m_metadata.inode = { fsid(), 1 };
|
||||
m_root_inode->m_metadata.mode = S_IFDIR
|
||||
| S_IROTH | S_IRGRP | S_IRUSR
|
||||
| S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
m_root_inode->m_metadata.uid = 0;
|
||||
m_root_inode->m_metadata.gid = 0;
|
||||
m_root_inode->m_metadata.size = 0;
|
||||
m_root_inode->m_metadata.mtime = TimeManagement::boot_time();
|
||||
return {};
|
||||
}
|
||||
|
||||
static unsigned inode_index_to_loop_index(InodeIndex inode_index)
|
||||
{
|
||||
VERIFY(inode_index > 1);
|
||||
return inode_index.value() - 2;
|
||||
}
|
||||
|
||||
Inode& DevLoopFS::root_inode()
|
||||
{
|
||||
return *m_root_inode;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<Inode>> DevLoopFS::get_inode(InodeIdentifier inode_id) const
|
||||
{
|
||||
if (inode_id.index() == 1)
|
||||
return *m_root_inode;
|
||||
|
||||
unsigned loop_index = inode_index_to_loop_index(inode_id.index());
|
||||
auto device = DeviceManagement::the().get_device(20, loop_index);
|
||||
VERIFY(device);
|
||||
|
||||
auto& loop_device = static_cast<LoopDevice&>(*device);
|
||||
auto inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) DevLoopFSInode(const_cast<DevLoopFS&>(*this), inode_id.index(), loop_device)));
|
||||
inode->m_metadata.inode = inode_id;
|
||||
inode->m_metadata.size = 0;
|
||||
inode->m_metadata.uid = 0;
|
||||
inode->m_metadata.gid = 0;
|
||||
inode->m_metadata.mode = S_IFCHR | S_IRUSR | S_IWUSR;
|
||||
inode->m_metadata.major_device = device->major();
|
||||
inode->m_metadata.minor_device = device->minor();
|
||||
inode->m_metadata.mtime = TimeManagement::boot_time();
|
||||
return inode;
|
||||
}
|
||||
|
||||
}
|
39
Kernel/FileSystem/DevLoopFS/FileSystem.h
Normal file
39
Kernel/FileSystem/DevLoopFS/FileSystem.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/FileSystem/FileSystem.h>
|
||||
#include <Kernel/FileSystem/Inode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class LoopDevice;
|
||||
class DevLoopFSInode;
|
||||
|
||||
class DevLoopFS final : public FileSystem {
|
||||
friend class DevLoopFSInode;
|
||||
|
||||
public:
|
||||
virtual ~DevLoopFS() override;
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> try_create(ReadonlyBytes);
|
||||
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual StringView class_name() const override { return "DevLoopFS"sv; }
|
||||
|
||||
virtual Inode& root_inode() override;
|
||||
|
||||
private:
|
||||
virtual u8 internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const override;
|
||||
|
||||
DevLoopFS();
|
||||
ErrorOr<NonnullRefPtr<Inode>> get_inode(InodeIdentifier) const;
|
||||
|
||||
RefPtr<DevLoopFSInode> m_root_inode;
|
||||
};
|
||||
|
||||
}
|
124
Kernel/FileSystem/DevLoopFS/Inode.cpp
Normal file
124
Kernel/FileSystem/DevLoopFS/Inode.cpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/StringView.h>
|
||||
#include <Kernel/Devices/DeviceManagement.h>
|
||||
#include <Kernel/Devices/Loop/LoopDevice.h>
|
||||
#include <Kernel/FileSystem/DevLoopFS/Inode.h>
|
||||
#include <Kernel/FileSystem/RAMBackedFileType.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
static InodeIndex loop_index_to_inode_index(unsigned loop_index)
|
||||
{
|
||||
return loop_index + 2;
|
||||
}
|
||||
|
||||
DevLoopFSInode::DevLoopFSInode(DevLoopFS& fs, InodeIndex index, LoopDevice& loop_device)
|
||||
: Inode(fs, index)
|
||||
, m_loop_device(loop_device)
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: This constructor is used for the root inode only.
|
||||
DevLoopFSInode::DevLoopFSInode(DevLoopFS& fs)
|
||||
: Inode(fs, 1)
|
||||
{
|
||||
}
|
||||
|
||||
DevLoopFSInode::~DevLoopFSInode() = default;
|
||||
|
||||
ErrorOr<size_t> DevLoopFSInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<size_t> DevLoopFSInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
InodeMetadata DevLoopFSInode::metadata() const
|
||||
{
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
{
|
||||
if (identifier().index() > 1)
|
||||
return ENOTDIR;
|
||||
|
||||
TRY(callback({ "."sv, identifier(), to_underlying(RAMBackedFileType::Directory) }));
|
||||
TRY(callback({ ".."sv, identifier(), to_underlying(RAMBackedFileType::Directory) }));
|
||||
|
||||
return LoopDevice::all_instances().with([&](auto& list) -> ErrorOr<void> {
|
||||
StringBuilder builder;
|
||||
for (LoopDevice& loop_device : list) {
|
||||
builder.clear();
|
||||
TRY(builder.try_appendff("{}", loop_device.index()));
|
||||
TRY(callback({ builder.string_view(), { fsid(), loop_index_to_inode_index(loop_device.index()) }, to_underlying(RAMBackedFileType::Block) }));
|
||||
}
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<Inode>> DevLoopFSInode::lookup(StringView name)
|
||||
{
|
||||
VERIFY(identifier().index() == 1);
|
||||
|
||||
if (name == "." || name == "..")
|
||||
return *this;
|
||||
|
||||
auto loop_index = name.to_number<unsigned>();
|
||||
if (!loop_index.has_value())
|
||||
return ENOENT;
|
||||
|
||||
return LoopDevice::all_instances().with([&](auto& list) -> ErrorOr<NonnullRefPtr<Inode>> {
|
||||
for (LoopDevice& loop_device : list) {
|
||||
if (loop_device.index() != loop_index.value())
|
||||
continue;
|
||||
return fs().get_inode({ fsid(), loop_index_to_inode_index(loop_index.value()) });
|
||||
}
|
||||
return ENOENT;
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::flush_metadata()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::add_child(Inode&, StringView, mode_t)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<Inode>> DevLoopFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::remove_child(StringView)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::replace_child(StringView, Inode&)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::chmod(mode_t)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> DevLoopFSInode::chown(UserID, GroupID)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
}
|
49
Kernel/FileSystem/DevLoopFS/Inode.h
Normal file
49
Kernel/FileSystem/DevLoopFS/Inode.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/Devices/Loop/LoopDevice.h>
|
||||
#include <Kernel/FileSystem/DevLoopFS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/Inode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class DevLoopFSInode final : public Inode {
|
||||
friend class DevLoopFS;
|
||||
|
||||
public:
|
||||
virtual ~DevLoopFSInode() override;
|
||||
|
||||
DevLoopFS& fs() { return static_cast<DevLoopFS&>(Inode::fs()); }
|
||||
DevLoopFS const& fs() const { return static_cast<DevLoopFS const&>(Inode::fs()); }
|
||||
|
||||
private:
|
||||
DevLoopFSInode(DevLoopFS&, InodeIndex, LoopDevice&);
|
||||
|
||||
// NOTE: This constructor is used for the root inode only.
|
||||
DevLoopFSInode(DevLoopFS&);
|
||||
|
||||
// ^Inode
|
||||
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<NonnullRefPtr<Inode>> lookup(StringView name) override;
|
||||
virtual ErrorOr<void> flush_metadata() override;
|
||||
virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override;
|
||||
virtual ErrorOr<NonnullRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override;
|
||||
virtual ErrorOr<void> add_child(Inode&, StringView name, mode_t) override;
|
||||
virtual ErrorOr<void> remove_child(StringView name) override;
|
||||
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
|
||||
virtual ErrorOr<void> chmod(mode_t) override;
|
||||
virtual ErrorOr<void> chown(UserID, GroupID) override;
|
||||
|
||||
LockWeakPtr<LoopDevice> m_loop_device;
|
||||
InodeMetadata m_metadata;
|
||||
};
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
#include <Kernel/Sections.h>
|
||||
#include <Kernel/Tasks/Process.h>
|
||||
|
||||
#include <Kernel/FileSystem/DevLoopFS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/DevPtsFS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/Ext2FS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/FATFS/FileSystem.h>
|
||||
|
@ -68,6 +69,7 @@ static constexpr FileSystemInitializer s_initializers[] = {
|
|||
{ "9p"sv, "Plan9FS"sv, true, true, true, Plan9FS::try_create, {}, handle_mount_boolean_flag_as_invalid, handle_mount_unsigned_integer_flag_as_invalid, handle_mount_signed_integer_flag_as_invalid, handle_mount_ascii_string_flag_as_invalid },
|
||||
{ "iso9660"sv, "ISO9660FS"sv, true, true, true, ISO9660FS::try_create, {}, handle_mount_boolean_flag_as_invalid, handle_mount_unsigned_integer_flag_as_invalid, handle_mount_signed_integer_flag_as_invalid, handle_mount_ascii_string_flag_as_invalid },
|
||||
{ "fat"sv, "FATFS"sv, true, true, true, FATFS::try_create, {}, handle_mount_boolean_flag_as_invalid, handle_mount_unsigned_integer_flag_as_invalid, handle_mount_signed_integer_flag_as_invalid, handle_mount_ascii_string_flag_as_invalid },
|
||||
{ "devloop"sv, "DevLoopFS"sv, false, false, false, {}, DevLoopFS::try_create, handle_mount_boolean_flag_as_invalid, handle_mount_unsigned_integer_flag_as_invalid, handle_mount_signed_integer_flag_as_invalid, handle_mount_ascii_string_flag_as_invalid },
|
||||
};
|
||||
|
||||
ErrorOr<FileSystemInitializer const*> VirtualFileSystem::find_filesystem_type_initializer(StringView fs_type)
|
||||
|
|
Loading…
Reference in a new issue