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:
Liav A 2022-05-28 15:42:03 +03:00 committed by Linus Groh
parent 4c588441e3
commit 58acdce41f
17 changed files with 72 additions and 88 deletions

View file

@ -12,9 +12,9 @@
namespace Kernel { namespace Kernel {
ErrorOr<NonnullRefPtr<DevPtsFS>> DevPtsFS::try_create() ErrorOr<NonnullRefPtr<FileSystem>> DevPtsFS::try_create()
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) DevPtsFS); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) DevPtsFS));
} }
DevPtsFS::DevPtsFS() = default; DevPtsFS::DevPtsFS() = default;

View file

@ -20,7 +20,7 @@ class DevPtsFS final : public FileSystem {
public: public:
virtual ~DevPtsFS() override; virtual ~DevPtsFS() override;
static ErrorOr<NonnullRefPtr<DevPtsFS>> try_create(); static ErrorOr<NonnullRefPtr<FileSystem>> try_create();
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;
virtual StringView class_name() const override { return "DevPtsFS"sv; } virtual StringView class_name() const override { return "DevPtsFS"sv; }

View file

@ -11,9 +11,9 @@
namespace Kernel { namespace Kernel {
ErrorOr<NonnullRefPtr<DevTmpFS>> DevTmpFS::try_create() ErrorOr<NonnullRefPtr<FileSystem>> DevTmpFS::try_create()
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) DevTmpFS); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) DevTmpFS));
} }
DevTmpFS::DevTmpFS() = default; DevTmpFS::DevTmpFS() = default;

View file

@ -20,7 +20,7 @@ class DevTmpFS final : public FileSystem {
public: public:
virtual ~DevTmpFS() override; virtual ~DevTmpFS() override;
static ErrorOr<NonnullRefPtr<DevTmpFS>> try_create(); static ErrorOr<NonnullRefPtr<FileSystem>> try_create();
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;
virtual StringView class_name() const override { return "DevTmpFS"sv; } virtual StringView class_name() const override { return "DevTmpFS"sv; }

View file

@ -49,9 +49,9 @@ static u8 to_ext2_file_type(mode_t mode)
return EXT2_FT_UNKNOWN; return EXT2_FT_UNKNOWN;
} }
ErrorOr<NonnullRefPtr<Ext2FS>> Ext2FS::try_create(OpenFileDescription& file_description) ErrorOr<NonnullRefPtr<FileSystem>> Ext2FS::try_create(OpenFileDescription& file_description)
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) Ext2FS(file_description)); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Ext2FS(file_description)));
} }
Ext2FS::Ext2FS(OpenFileDescription& file_description) Ext2FS::Ext2FS(OpenFileDescription& file_description)

View file

@ -86,7 +86,7 @@ public:
FileSize64bits = 1 << 1, FileSize64bits = 1 << 1,
}; };
static ErrorOr<NonnullRefPtr<Ext2FS>> try_create(OpenFileDescription&); static ErrorOr<NonnullRefPtr<FileSystem>> try_create(OpenFileDescription&);
virtual ~Ext2FS() override; virtual ~Ext2FS() override;
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;

View file

@ -168,9 +168,9 @@ private:
Vector<DirectoryState> m_directory_stack; Vector<DirectoryState> m_directory_stack;
}; };
ErrorOr<NonnullRefPtr<ISO9660FS>> ISO9660FS::try_create(OpenFileDescription& description) ErrorOr<NonnullRefPtr<FileSystem>> ISO9660FS::try_create(OpenFileDescription& description)
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) ISO9660FS(description)); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ISO9660FS(description)));
} }
ISO9660FS::ISO9660FS(OpenFileDescription& description) ISO9660FS::ISO9660FS(OpenFileDescription& description)

View file

@ -305,7 +305,7 @@ public:
} }
}; };
static ErrorOr<NonnullRefPtr<ISO9660FS>> try_create(OpenFileDescription&); static ErrorOr<NonnullRefPtr<FileSystem>> try_create(OpenFileDescription&);
virtual ~ISO9660FS() override; virtual ~ISO9660FS() override;
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;

View file

@ -9,9 +9,9 @@
namespace Kernel { namespace Kernel {
ErrorOr<NonnullRefPtr<Plan9FS>> Plan9FS::try_create(OpenFileDescription& file_description) ErrorOr<NonnullRefPtr<FileSystem>> Plan9FS::try_create(OpenFileDescription& file_description)
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) Plan9FS(file_description)); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Plan9FS(file_description)));
} }
Plan9FS::Plan9FS(OpenFileDescription& file_description) Plan9FS::Plan9FS(OpenFileDescription& file_description)

View file

@ -20,7 +20,7 @@ class Plan9FS final : public FileBackedFileSystem {
public: public:
virtual ~Plan9FS() override; virtual ~Plan9FS() override;
static ErrorOr<NonnullRefPtr<Plan9FS>> try_create(OpenFileDescription&); static ErrorOr<NonnullRefPtr<FileSystem>> try_create(OpenFileDescription&);
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;

View file

@ -37,9 +37,9 @@ UNMAP_AFTER_INIT ProcFSComponentRegistry::ProcFSComponentRegistry()
{ {
} }
ErrorOr<NonnullRefPtr<ProcFS>> ProcFS::try_create() ErrorOr<NonnullRefPtr<FileSystem>> ProcFS::try_create()
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFS()); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ProcFS));
} }
ProcFS::ProcFS() = default; ProcFS::ProcFS() = default;

View file

@ -28,7 +28,7 @@ class ProcFS final : public FileSystem {
public: public:
virtual ~ProcFS() override; virtual ~ProcFS() override;
static ErrorOr<NonnullRefPtr<ProcFS>> try_create(); static ErrorOr<NonnullRefPtr<FileSystem>> try_create();
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;
virtual StringView class_name() const override { return "ProcFS"sv; } virtual StringView class_name() const override { return "ProcFS"sv; }

View file

@ -68,9 +68,9 @@ SysFSRootDirectory::SysFSRootDirectory()
m_buses_directory = buses_directory; m_buses_directory = buses_directory;
} }
ErrorOr<NonnullRefPtr<SysFS>> SysFS::try_create() ErrorOr<NonnullRefPtr<FileSystem>> SysFS::try_create()
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) SysFS); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SysFS));
} }
SysFS::SysFS() = default; SysFS::SysFS() = default;

View file

@ -118,7 +118,7 @@ class SysFS final : public FileSystem {
public: public:
virtual ~SysFS() override; virtual ~SysFS() override;
static ErrorOr<NonnullRefPtr<SysFS>> try_create(); static ErrorOr<NonnullRefPtr<FileSystem>> try_create();
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;
virtual StringView class_name() const override { return "SysFS"sv; } virtual StringView class_name() const override { return "SysFS"sv; }

View file

@ -10,9 +10,9 @@
namespace Kernel { namespace Kernel {
ErrorOr<NonnullRefPtr<TmpFS>> TmpFS::try_create() ErrorOr<NonnullRefPtr<FileSystem>> TmpFS::try_create()
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) TmpFS); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) TmpFS));
} }
TmpFS::TmpFS() = default; TmpFS::TmpFS() = default;

View file

@ -19,7 +19,7 @@ class TmpFS final : public FileSystem {
public: public:
virtual ~TmpFS() override; virtual ~TmpFS() override;
static ErrorOr<NonnullRefPtr<TmpFS>> try_create(); static ErrorOr<NonnullRefPtr<FileSystem>> try_create();
virtual ErrorOr<void> initialize() override; virtual ErrorOr<void> initialize() override;
virtual StringView class_name() const override { return "TmpFS"sv; } virtual StringView class_name() const override { return "TmpFS"sv; }

View file

@ -18,61 +18,52 @@
namespace Kernel { namespace Kernel {
static ErrorOr<NonnullRefPtr<FileSystem>> create_ram_backed_filesystem_instance(StringView fs_type) struct FileSystemInitializer {
{ StringView short_name;
RefPtr<FileSystem> fs; StringView name;
if (fs_type == "proc"sv || fs_type == "ProcFS"sv) { bool requires_open_file_description { false };
fs = TRY(ProcFS::try_create()); bool requires_block_device { false };
} else if (fs_type == "devpts"sv || fs_type == "DevPtsFS"sv) { bool requires_seekable_file { false };
fs = TRY(DevPtsFS::try_create()); ErrorOr<NonnullRefPtr<FileSystem>> (*create_with_fd)(OpenFileDescription&) = nullptr;
} else if (fs_type == "dev"sv || fs_type == "DevTmpFS"sv) { ErrorOr<NonnullRefPtr<FileSystem>> (*create)(void) = nullptr;
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();
}
static bool filesystem_mount_require_open_file_description(StringView fs_type) static constexpr FileSystemInitializer s_initializers[] = {
{ { "proc"sv, "ProcFS"sv, false, false, false, {}, ProcFS::try_create },
if (fs_type == "ext2"sv || fs_type == "Ext2FS"sv) { { "devpts"sv, "DevPtsFS"sv, false, false, false, {}, DevPtsFS::try_create },
return true; { "dev"sv, "DevTmpFS"sv, false, false, false, {}, DevTmpFS::try_create },
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) { { "sys"sv, "SysFS"sv, false, false, false, {}, SysFS::try_create },
return true; { "tmp"sv, "TmpFS"sv, false, false, false, {}, TmpFS::try_create },
} else if (fs_type == "iso9660"sv || fs_type == "ISO9660FS"sv) { { "ext2"sv, "Ext2FS"sv, true, true, true, Ext2FS::try_create, {} },
return true; { "9p"sv, "Plan9FS"sv, true, true, true, Plan9FS::try_create, {} },
} { "iso9660"sv, "ISO9660FS"sv, true, true, true, ISO9660FS::try_create, {} },
return false; };
}
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 (initializer_entry.requires_block_device && !description.file().is_block_device())
if (!description.file().is_block_device())
return ENOTBLK; 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"); dbgln("mount: this is not a seekable file");
return ENODEV; return ENODEV;
} }
fs = TRY(Ext2FS::try_create(description)); NonnullRefPtr<FileSystem> fs = TRY(initializer_entry.create_with_fd(description));
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) { return fs;
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));
} }
if (!fs) return ENODEV;
return ENODEV;
return fs.release_nonnull();
} }
ErrorOr<FlatPtr> Process::sys$mount(Userspace<Syscall::SC_mount_params const*> user_params) 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; return 0;
} }
// Note: Try to determine as early as possible if we deal with a filesystem type RefPtr<FileSystem> fs;
// that must be backed by a open file description, so if there's no such valid
// description, we can fail with EBADF now. if (!description_or_error.is_error()) {
if (filesystem_mount_require_open_file_description(fs_type) && description_or_error.is_error()) { auto description = description_or_error.release_value();
return EBADF; 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()) { TRY(fs->initialize());
auto synthetic_filesystem = TRY(create_ram_backed_filesystem_instance(fs_type)); TRY(VirtualFileSystem::the().mount(*fs, target_custody, params.flags));
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));
return 0; return 0;
} }