mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:57:45 +00:00
Kernel/FileSystem: Simplify even more the mount syscall
As with the previous commit, we put a distinction between filesystems that require a file description and those which don't, but now in a much more readable mechanism - all initialization properties as well as the create static method are grouped to create the FileSystemInitializer structure. Then when we need to initialize an instance, we iterate over a table of these structures, checking for matching structure and then validating the given arguments from userspace against the requirements to ensure we can create a valid instance of the requested filesystem.
This commit is contained in:
parent
4c588441e3
commit
58acdce41f
17 changed files with 72 additions and 88 deletions
|
@ -18,61 +18,52 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> create_ram_backed_filesystem_instance(StringView fs_type)
|
||||
{
|
||||
RefPtr<FileSystem> fs;
|
||||
if (fs_type == "proc"sv || fs_type == "ProcFS"sv) {
|
||||
fs = TRY(ProcFS::try_create());
|
||||
} else if (fs_type == "devpts"sv || fs_type == "DevPtsFS"sv) {
|
||||
fs = TRY(DevPtsFS::try_create());
|
||||
} else if (fs_type == "dev"sv || fs_type == "DevTmpFS"sv) {
|
||||
fs = TRY(DevTmpFS::try_create());
|
||||
} else if (fs_type == "sys"sv || fs_type == "SysFS"sv) {
|
||||
fs = TRY(SysFS::try_create());
|
||||
} else if (fs_type == "tmp"sv || fs_type == "TmpFS"sv) {
|
||||
fs = TRY(TmpFS::try_create());
|
||||
}
|
||||
if (!fs)
|
||||
return ENODEV;
|
||||
return fs.release_nonnull();
|
||||
}
|
||||
struct FileSystemInitializer {
|
||||
StringView short_name;
|
||||
StringView name;
|
||||
bool requires_open_file_description { false };
|
||||
bool requires_block_device { false };
|
||||
bool requires_seekable_file { false };
|
||||
ErrorOr<NonnullRefPtr<FileSystem>> (*create_with_fd)(OpenFileDescription&) = nullptr;
|
||||
ErrorOr<NonnullRefPtr<FileSystem>> (*create)(void) = nullptr;
|
||||
};
|
||||
|
||||
static bool filesystem_mount_require_open_file_description(StringView fs_type)
|
||||
{
|
||||
if (fs_type == "ext2"sv || fs_type == "Ext2FS"sv) {
|
||||
return true;
|
||||
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) {
|
||||
return true;
|
||||
} else if (fs_type == "iso9660"sv || fs_type == "ISO9660FS"sv) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static constexpr FileSystemInitializer s_initializers[] = {
|
||||
{ "proc"sv, "ProcFS"sv, false, false, false, {}, ProcFS::try_create },
|
||||
{ "devpts"sv, "DevPtsFS"sv, false, false, false, {}, DevPtsFS::try_create },
|
||||
{ "dev"sv, "DevTmpFS"sv, false, false, false, {}, DevTmpFS::try_create },
|
||||
{ "sys"sv, "SysFS"sv, false, false, false, {}, SysFS::try_create },
|
||||
{ "tmp"sv, "TmpFS"sv, false, false, false, {}, TmpFS::try_create },
|
||||
{ "ext2"sv, "Ext2FS"sv, true, true, true, Ext2FS::try_create, {} },
|
||||
{ "9p"sv, "Plan9FS"sv, true, true, true, Plan9FS::try_create, {} },
|
||||
{ "iso9660"sv, "ISO9660FS"sv, true, true, true, ISO9660FS::try_create, {} },
|
||||
};
|
||||
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> create_open_file_description_backed_filesystem_instance(StringView fs_type, OpenFileDescription& description)
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> create_filesystem_instance(StringView fs_type, OpenFileDescription* possible_description)
|
||||
{
|
||||
RefPtr<FileSystem> fs;
|
||||
for (auto& initializer_entry : s_initializers) {
|
||||
if (fs_type != initializer_entry.short_name && fs_type != initializer_entry.name)
|
||||
continue;
|
||||
if (!initializer_entry.requires_open_file_description) {
|
||||
VERIFY(initializer_entry.create);
|
||||
NonnullRefPtr<FileSystem> fs = TRY(initializer_entry.create());
|
||||
return fs;
|
||||
}
|
||||
VERIFY(initializer_entry.create_with_fd);
|
||||
if (!possible_description)
|
||||
return EBADF;
|
||||
OpenFileDescription& description = *possible_description;
|
||||
|
||||
if (fs_type == "ext2"sv || fs_type == "Ext2FS"sv) {
|
||||
if (!description.file().is_block_device())
|
||||
if (initializer_entry.requires_block_device && !description.file().is_block_device())
|
||||
return ENOTBLK;
|
||||
if (!description.file().is_seekable()) {
|
||||
if (initializer_entry.requires_seekable_file && !description.file().is_seekable()) {
|
||||
dbgln("mount: this is not a seekable file");
|
||||
return ENODEV;
|
||||
}
|
||||
fs = TRY(Ext2FS::try_create(description));
|
||||
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) {
|
||||
fs = TRY(Plan9FS::try_create(description));
|
||||
} else if (fs_type == "iso9660"sv || fs_type == "ISO9660FS"sv) {
|
||||
if (!description.file().is_seekable()) {
|
||||
dbgln("mount: this is not a seekable file");
|
||||
return ENODEV;
|
||||
}
|
||||
fs = TRY(ISO9660FS::try_create(description));
|
||||
NonnullRefPtr<FileSystem> fs = TRY(initializer_entry.create_with_fd(description));
|
||||
return fs;
|
||||
}
|
||||
if (!fs)
|
||||
return ENODEV;
|
||||
return fs.release_nonnull();
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
ErrorOr<FlatPtr> Process::sys$mount(Userspace<Syscall::SC_mount_params const*> user_params)
|
||||
|
@ -116,26 +107,19 @@ ErrorOr<FlatPtr> Process::sys$mount(Userspace<Syscall::SC_mount_params const*> u
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Note: Try to determine as early as possible if we deal with a filesystem type
|
||||
// that must be backed by a open file description, so if there's no such valid
|
||||
// description, we can fail with EBADF now.
|
||||
if (filesystem_mount_require_open_file_description(fs_type) && description_or_error.is_error()) {
|
||||
return EBADF;
|
||||
RefPtr<FileSystem> fs;
|
||||
|
||||
if (!description_or_error.is_error()) {
|
||||
auto description = description_or_error.release_value();
|
||||
fs = TRY(create_filesystem_instance(fs_type, description.ptr()));
|
||||
auto source_pseudo_path = TRY(description->pseudo_path());
|
||||
dbgln("mount: attempting to mount {} on {}", source_pseudo_path, target);
|
||||
} else {
|
||||
fs = TRY(create_filesystem_instance(fs_type, {}));
|
||||
}
|
||||
|
||||
if (description_or_error.is_error()) {
|
||||
auto synthetic_filesystem = TRY(create_ram_backed_filesystem_instance(fs_type));
|
||||
TRY(synthetic_filesystem->initialize());
|
||||
TRY(VirtualFileSystem::the().mount(*synthetic_filesystem, target_custody, params.flags));
|
||||
return 0;
|
||||
}
|
||||
auto description = description_or_error.release_value();
|
||||
auto open_file_description_backed_filesystem = TRY(create_open_file_description_backed_filesystem_instance(fs_type, description));
|
||||
auto source_pseudo_path = TRY(description->pseudo_path());
|
||||
dbgln("mount: attempting to mount {} on {}", source_pseudo_path, target);
|
||||
TRY(open_file_description_backed_filesystem->initialize());
|
||||
TRY(VirtualFileSystem::the().mount(*open_file_description_backed_filesystem, target_custody, params.flags));
|
||||
|
||||
TRY(fs->initialize());
|
||||
TRY(VirtualFileSystem::the().mount(*fs, target_custody, params.flags));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue