mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:52: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
				
			
		|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Liav A
						Liav A