From 0fd7b688af0b9b5a8976fb8b0acfeec68917101d Mon Sep 17 00:00:00 2001 From: Liav A Date: Sat, 20 Aug 2022 00:03:24 +0300 Subject: [PATCH] Kernel: Introduce support for using FileSystem object in multiple mounts The idea is to enable mounting FileSystem objects across multiple mounts in contrast to what happened until now - each mount has its own unique FileSystem object being attached to it. Considering a situation of mounting a block device at 2 different mount points at in system, there were a couple of critical flaws due to how the previous "design" worked: 1. BlockBasedFileSystem(s) that pointed to the same actual device had a separate DiskCache object being attached to them. Because both instances were not synchronized by any means, corruption of the filesystem is most likely achieveable by a simple cache flush of either of the instances. 2. For superblock-oriented filesystems (such as the ext2 filesystem), lack of synchronization between both instances can lead to severe corruption in the superblock, which could render the entire filesystem unusable. 3. Flags of a specific filesystem implementation (for example, with xfs on Linux, one can instruct to mount it with the discard option) must be honored across multiple mounts, to ensure expected behavior against a particular filesystem. This patch put the foundations to start fix the issues mentioned above. However, there are still major issues to solve, so this is only a start. --- Kernel/FileSystem/BlockBasedFileSystem.cpp | 4 +- Kernel/FileSystem/BlockBasedFileSystem.h | 3 +- Kernel/FileSystem/Ext2FileSystem.cpp | 15 ++++++-- Kernel/FileSystem/Ext2FileSystem.h | 7 ++-- Kernel/FileSystem/FATFileSystem.cpp | 13 +++++-- Kernel/FileSystem/FATFileSystem.h | 7 +++- Kernel/FileSystem/FileBackedFileSystem.cpp | 8 ++++ Kernel/FileSystem/FileBackedFileSystem.h | 13 ++++++- Kernel/FileSystem/FileSystem.cpp | 9 +++++ Kernel/FileSystem/FileSystem.h | 8 +++- Kernel/FileSystem/ISO9660FileSystem.cpp | 19 +++++++++- Kernel/FileSystem/ISO9660FileSystem.h | 6 ++- Kernel/FileSystem/Plan9FileSystem.cpp | 17 ++++++++- Kernel/FileSystem/Plan9FileSystem.h | 7 +++- Kernel/FileSystem/VirtualFileSystem.cpp | 43 ++++++++++++++++++++-- Kernel/FileSystem/VirtualFileSystem.h | 7 +++- Kernel/Syscalls/mount.cpp | 15 ++++---- 17 files changed, 168 insertions(+), 33 deletions(-) diff --git a/Kernel/FileSystem/BlockBasedFileSystem.cpp b/Kernel/FileSystem/BlockBasedFileSystem.cpp index ab2cd21689..b343022ecf 100644 --- a/Kernel/FileSystem/BlockBasedFileSystem.cpp +++ b/Kernel/FileSystem/BlockBasedFileSystem.cpp @@ -116,8 +116,10 @@ BlockBasedFileSystem::BlockBasedFileSystem(OpenFileDescription& file_description BlockBasedFileSystem::~BlockBasedFileSystem() = default; -ErrorOr BlockBasedFileSystem::initialize() +ErrorOr BlockBasedFileSystem::initialize_while_locked() { + VERIFY(m_lock.is_locked()); + VERIFY(!is_initialized_while_locked()); VERIFY(block_size() != 0); auto cached_block_data = TRY(KBuffer::try_create_with_size("BlockBasedFS: Cache blocks"sv, DiskCache::EntryCount * block_size())); auto entries_data = TRY(KBuffer::try_create_with_size("BlockBasedFS: Cache entries"sv, DiskCache::EntryCount * sizeof(CacheEntry))); diff --git a/Kernel/FileSystem/BlockBasedFileSystem.h b/Kernel/FileSystem/BlockBasedFileSystem.h index 47a25ec8f2..817747a482 100644 --- a/Kernel/FileSystem/BlockBasedFileSystem.h +++ b/Kernel/FileSystem/BlockBasedFileSystem.h @@ -16,7 +16,6 @@ public: AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, BlockIndex); virtual ~BlockBasedFileSystem() override; - virtual ErrorOr initialize() override; u64 logical_block_size() const { return m_logical_block_size; }; @@ -26,6 +25,8 @@ public: protected: explicit BlockBasedFileSystem(OpenFileDescription&); + virtual ErrorOr initialize_while_locked() override; + ErrorOr read_block(BlockIndex, UserOrKernelBuffer*, size_t count, u64 offset = 0, bool allow_cache = true) const; ErrorOr read_blocks(BlockIndex, unsigned count, UserOrKernelBuffer&, bool allow_cache = true) const; diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp index fadf67888f..e36f63e5f5 100644 --- a/Kernel/FileSystem/Ext2FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FileSystem.cpp @@ -77,9 +77,16 @@ ext2_group_desc const& Ext2FS::group_descriptor(GroupIndex group_index) const return block_group_descriptors()[group_index.value() - 1]; } -ErrorOr Ext2FS::initialize() +bool Ext2FS::is_initialized_while_locked() { - MutexLocker locker(m_lock); + VERIFY(m_lock.is_locked()); + return !m_root_inode.is_null(); +} + +ErrorOr Ext2FS::initialize_while_locked() +{ + VERIFY(m_lock.is_locked()); + VERIFY(!is_initialized_while_locked()); VERIFY((sizeof(ext2_super_block) % logical_block_size()) == 0); auto super_block_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&m_super_block); @@ -109,7 +116,7 @@ ErrorOr Ext2FS::initialize() set_fragment_size(EXT2_FRAG_SIZE(&super_block)); // Note: This depends on the block size being available. - TRY(BlockBasedFileSystem::initialize()); + TRY(BlockBasedFileSystem::initialize_while_locked()); VERIFY(block_size() <= (int)max_block_size); @@ -1680,7 +1687,7 @@ unsigned Ext2FS::free_inode_count() const return super_block().s_free_inodes_count; } -ErrorOr Ext2FS::prepare_to_unmount() +ErrorOr Ext2FS::prepare_to_clear_last_mount() { MutexLocker locker(m_lock); diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h index 9c65ee68f4..9d22d04a42 100644 --- a/Kernel/FileSystem/Ext2FileSystem.h +++ b/Kernel/FileSystem/Ext2FileSystem.h @@ -91,15 +91,12 @@ public: static ErrorOr> try_create(OpenFileDescription&); virtual ~Ext2FS() override; - virtual ErrorOr initialize() override; virtual unsigned total_block_count() const override; virtual unsigned free_block_count() const override; virtual unsigned total_inode_count() const override; virtual unsigned free_inode_count() const override; - virtual ErrorOr prepare_to_unmount() override; - virtual bool supports_watchers() const override { return true; } virtual u8 internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const override; @@ -126,6 +123,10 @@ private: ErrorOr flush_super_block(); + virtual ErrorOr initialize_while_locked() override; + virtual bool is_initialized_while_locked() override; + + virtual ErrorOr prepare_to_clear_last_mount() override; virtual StringView class_name() const override { return "Ext2FS"sv; } virtual Ext2FSInode& root_inode() override; ErrorOr> get_inode(InodeIdentifier) const; diff --git a/Kernel/FileSystem/FATFileSystem.cpp b/Kernel/FileSystem/FATFileSystem.cpp index ee06488b86..431c95ff8f 100644 --- a/Kernel/FileSystem/FATFileSystem.cpp +++ b/Kernel/FileSystem/FATFileSystem.cpp @@ -22,9 +22,16 @@ FATFS::FATFS(OpenFileDescription& file_description) { } -ErrorOr FATFS::initialize() +bool FATFS::is_initialized_while_locked() { - MutexLocker locker(m_lock); + VERIFY(m_lock.is_locked()); + return !m_root_inode.is_null(); +} + +ErrorOr FATFS::initialize_while_locked() +{ + VERIFY(m_lock.is_locked()); + VERIFY(!is_initialized_while_locked()); m_boot_record = TRY(KBuffer::try_create_with_size("FATFS: Boot Record"sv, m_logical_block_size)); auto boot_record_buffer = UserOrKernelBuffer::for_kernel_buffer(m_boot_record->data()); @@ -63,7 +70,7 @@ ErrorOr FATFS::initialize() u32 root_directory_sectors = ((boot_record()->root_directory_entry_count * sizeof(FATEntry)) + (m_logical_block_size - 1)) / m_logical_block_size; m_first_data_sector = boot_record()->reserved_sector_count + (boot_record()->fat_count * boot_record()->sectors_per_fat) + root_directory_sectors; - TRY(BlockBasedFileSystem::initialize()); + TRY(BlockBasedFileSystem::initialize_while_locked()); FATEntry root_entry {}; diff --git a/Kernel/FileSystem/FATFileSystem.h b/Kernel/FileSystem/FATFileSystem.h index 807191aaa3..61cc30d437 100644 --- a/Kernel/FileSystem/FATFileSystem.h +++ b/Kernel/FileSystem/FATFileSystem.h @@ -116,11 +116,16 @@ public: static ErrorOr> try_create(OpenFileDescription&); virtual ~FATFS() override = default; - virtual ErrorOr initialize() override; virtual StringView class_name() const override { return "FATFS"sv; } virtual Inode& root_inode() override; private: + virtual ErrorOr initialize_while_locked() override; + virtual bool is_initialized_while_locked() override; + // FIXME: This is not a proper way to clear last mount of a FAT filesystem, + // but for now we simply have no other way to properly do it. + virtual ErrorOr prepare_to_clear_last_mount() override { return {}; } + FATFS(OpenFileDescription&); static constexpr u8 signature_1 = 0x28; diff --git a/Kernel/FileSystem/FileBackedFileSystem.cpp b/Kernel/FileSystem/FileBackedFileSystem.cpp index ab0c1e97e4..f67a75f48b 100644 --- a/Kernel/FileSystem/FileBackedFileSystem.cpp +++ b/Kernel/FileSystem/FileBackedFileSystem.cpp @@ -15,4 +15,12 @@ FileBackedFileSystem::FileBackedFileSystem(OpenFileDescription& file_description FileBackedFileSystem::~FileBackedFileSystem() = default; +ErrorOr FileBackedFileSystem::initialize() +{ + MutexLocker locker(m_lock); + if (is_initialized_while_locked()) + return {}; + return initialize_while_locked(); +} + } diff --git a/Kernel/FileSystem/FileBackedFileSystem.h b/Kernel/FileSystem/FileBackedFileSystem.h index e959bb729c..8bfb1a1b6f 100644 --- a/Kernel/FileSystem/FileBackedFileSystem.h +++ b/Kernel/FileSystem/FileBackedFileSystem.h @@ -12,6 +12,8 @@ namespace Kernel { class FileBackedFileSystem : public FileSystem { + friend class VirtualFileSystem; + public: virtual ~FileBackedFileSystem() override; @@ -23,10 +25,19 @@ public: protected: explicit FileBackedFileSystem(OpenFileDescription&); + // Note: We require all FileBackedFileSystem to implement something that actually + // takes into account the fact that we will clean the last mount of the filesystem, + // therefore, removing the file system with it from the Kernel memory. + virtual ErrorOr prepare_to_clear_last_mount() override = 0; + + virtual ErrorOr initialize_while_locked() = 0; + virtual bool is_initialized_while_locked() = 0; + private: + virtual ErrorOr initialize() override final; virtual bool is_file_backed() const override { return true; } + IntrusiveListNode m_file_backed_file_system_node; mutable NonnullLockRefPtr m_file_description; }; - } diff --git a/Kernel/FileSystem/FileSystem.cpp b/Kernel/FileSystem/FileSystem.cpp index 4c3ea5959f..09f3bfc143 100644 --- a/Kernel/FileSystem/FileSystem.cpp +++ b/Kernel/FileSystem/FileSystem.cpp @@ -42,6 +42,15 @@ FileSystem* FileSystem::from_fsid(FileSystemID id) return nullptr; } +ErrorOr FileSystem::prepare_to_unmount() +{ + return m_attach_count.with([&](auto& attach_count) -> ErrorOr { + if (attach_count == 1) + return prepare_to_clear_last_mount(); + return {}; + }); +} + FileSystem::DirectoryEntryView::DirectoryEntryView(StringView n, InodeIdentifier i, u8 ft) : name(n) , inode(i) diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h index 7618cd5edf..4098884062 100644 --- a/Kernel/FileSystem/FileSystem.h +++ b/Kernel/FileSystem/FileSystem.h @@ -41,7 +41,7 @@ public: virtual unsigned total_inode_count() const { return 0; } virtual unsigned free_inode_count() const { return 0; } - virtual ErrorOr prepare_to_unmount() { return {}; } + ErrorOr prepare_to_unmount(); struct DirectoryEntryView { DirectoryEntryView(StringView name, InodeIdentifier, u8 file_type); @@ -61,12 +61,16 @@ public: // Converts file types that are used internally by the filesystem to DT_* types virtual u8 internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const { return entry.file_type; } + SpinlockProtected& mounted_count(Badge) { return m_attach_count; } + protected: FileSystem(); void set_block_size(u64 size) { m_block_size = size; } void set_fragment_size(size_t size) { m_fragment_size = size; } + virtual ErrorOr prepare_to_clear_last_mount() { return {}; } + mutable Mutex m_lock { "FS"sv }; private: @@ -74,6 +78,8 @@ private: u64 m_block_size { 0 }; size_t m_fragment_size { 0 }; bool m_readonly { false }; + + SpinlockProtected m_attach_count { LockRank::FileSystem, 0 }; }; inline FileSystem* InodeIdentifier::fs() // NOLINT(readability-make-member-function-const) const InodeIdentifiers should not be able to modify the FileSystem diff --git a/Kernel/FileSystem/ISO9660FileSystem.cpp b/Kernel/FileSystem/ISO9660FileSystem.cpp index c7fbf99f09..3061f868a8 100644 --- a/Kernel/FileSystem/ISO9660FileSystem.cpp +++ b/Kernel/FileSystem/ISO9660FileSystem.cpp @@ -182,9 +182,18 @@ ISO9660FS::ISO9660FS(OpenFileDescription& description) ISO9660FS::~ISO9660FS() = default; -ErrorOr ISO9660FS::initialize() +bool ISO9660FS::is_initialized_while_locked() { - TRY(BlockBasedFileSystem::initialize()); + VERIFY(m_lock.is_locked()); + return !m_root_inode.is_null(); +} + +ErrorOr ISO9660FS::initialize_while_locked() +{ + VERIFY(m_lock.is_locked()); + VERIFY(!is_initialized_while_locked()); + + TRY(BlockBasedFileSystem::initialize_while_locked()); TRY(parse_volume_set()); TRY(create_root_inode()); return {}; @@ -223,6 +232,12 @@ u8 ISO9660FS::internal_file_type_to_directory_entry_type(DirectoryEntryView cons return DT_REG; } +ErrorOr ISO9660FS::prepare_to_clear_last_mount() +{ + // FIXME: Do proper cleaning here. + return {}; +} + ErrorOr ISO9660FS::parse_volume_set() { VERIFY(!m_primary_volume); diff --git a/Kernel/FileSystem/ISO9660FileSystem.h b/Kernel/FileSystem/ISO9660FileSystem.h index db97de8480..dd44683766 100644 --- a/Kernel/FileSystem/ISO9660FileSystem.h +++ b/Kernel/FileSystem/ISO9660FileSystem.h @@ -308,7 +308,6 @@ public: static ErrorOr> try_create(OpenFileDescription&); virtual ~ISO9660FS() override; - virtual ErrorOr initialize() override; virtual StringView class_name() const override { return "ISO9660FS"sv; } virtual Inode& root_inode() override; @@ -322,6 +321,11 @@ public: private: ISO9660FS(OpenFileDescription&); + virtual ErrorOr prepare_to_clear_last_mount() override; + + virtual bool is_initialized_while_locked() override; + virtual ErrorOr initialize_while_locked() override; + ErrorOr parse_volume_set(); ErrorOr create_root_inode(); ErrorOr calculate_inode_count() const; diff --git a/Kernel/FileSystem/Plan9FileSystem.cpp b/Kernel/FileSystem/Plan9FileSystem.cpp index 882faaf35b..be2f4f18fb 100644 --- a/Kernel/FileSystem/Plan9FileSystem.cpp +++ b/Kernel/FileSystem/Plan9FileSystem.cpp @@ -20,6 +20,12 @@ Plan9FS::Plan9FS(OpenFileDescription& file_description) { } +ErrorOr Plan9FS::prepare_to_clear_last_mount() +{ + // FIXME: Do proper cleaning here. + return {}; +} + Plan9FS::~Plan9FS() { // Make sure to destroy the root inode before the FS gets destroyed. @@ -196,8 +202,17 @@ private: bool m_have_been_built { false }; }; -ErrorOr Plan9FS::initialize() +bool Plan9FS::is_initialized_while_locked() { + VERIFY(m_lock.is_locked()); + return !m_root_inode.is_null(); +} + +ErrorOr Plan9FS::initialize_while_locked() +{ + VERIFY(m_lock.is_locked()); + VERIFY(!is_initialized_while_locked()); + ensure_thread(); Message version_message { *this, Message::Type::Tversion }; diff --git a/Kernel/FileSystem/Plan9FileSystem.h b/Kernel/FileSystem/Plan9FileSystem.h index e5c59b90ce..ac3c6ad126 100644 --- a/Kernel/FileSystem/Plan9FileSystem.h +++ b/Kernel/FileSystem/Plan9FileSystem.h @@ -22,8 +22,6 @@ public: virtual ~Plan9FS() override; static ErrorOr> try_create(OpenFileDescription&); - virtual ErrorOr initialize() override; - virtual bool supports_watchers() const override { return false; } virtual Inode& root_inode() override; @@ -48,6 +46,11 @@ public: private: Plan9FS(OpenFileDescription&); + virtual ErrorOr prepare_to_clear_last_mount() override; + + virtual bool is_initialized_while_locked() override; + virtual ErrorOr initialize_while_locked() override; + class Blocker; class Plan9FSBlockerSet final : public Thread::BlockerSet { diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 5960a3a83b..df7f03ca6e 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -65,7 +65,8 @@ ErrorOr VirtualFileSystem::mount(FileSystem& fs, Custody& mount_point, int auto new_mount = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Mount(fs, &mount_point, flags))); return m_mounts.with([&](auto& mounts) -> ErrorOr { auto& inode = mount_point.inode(); - dbgln("VirtualFileSystem: Mounting {} at inode {} with flags {}", + dbgln("VirtualFileSystem: FileSystemID {}, Mounting {} at inode {} with flags {}", + fs.fsid(), fs.class_name(), inode.identifier(), flags); @@ -73,6 +74,10 @@ ErrorOr VirtualFileSystem::mount(FileSystem& fs, Custody& mount_point, int dbgln("VirtualFileSystem: Mounting unsuccessful - inode {} is already a mount-point.", inode.identifier()); return EBUSY; } + // Note: Actually add a mount for the filesystem and increment the filesystem mounted count + new_mount->guest_fs().mounted_count({}).with([&](auto& mounted_count) { + mounted_count++; + }); mounts.append(move(new_mount)); return {}; }); @@ -106,16 +111,24 @@ ErrorOr VirtualFileSystem::remount(Custody& mount_point, int new_flags) return {}; } -ErrorOr VirtualFileSystem::unmount(Inode& guest_inode) +ErrorOr VirtualFileSystem::unmount(Custody& mountpoint_custody) { - dbgln("VirtualFileSystem: unmount called with inode {}", guest_inode.identifier()); + auto& guest_inode = mountpoint_custody.inode(); + auto custody_path = TRY(mountpoint_custody.try_serialize_absolute_path()); + dbgln("VirtualFileSystem: unmount called with inode {} on mountpoint {}", guest_inode.identifier(), custody_path->view()); return m_mounts.with([&](auto& mounts) -> ErrorOr { for (size_t i = 0; i < mounts.size(); ++i) { auto& mount = mounts[i]; if (&mount->guest() != &guest_inode) continue; + auto mountpoint_path = TRY(mount->absolute_path()); + if (custody_path->view() != mountpoint_path->view()) + continue; TRY(mount->guest_fs().prepare_to_unmount()); + mount->guest_fs().mounted_count({}).with([&](auto& mounted_count) { + mounted_count--; + }); dbgln("VirtualFileSystem: Unmounting file system {}...", mount->guest_fs().fsid()); (void)mounts.unstable_take(i); return {}; @@ -142,9 +155,13 @@ ErrorOr VirtualFileSystem::mount_root(FileSystem& fs) m_root_inode = root_inode; auto pseudo_path = TRY(static_cast(fs).file_description().pseudo_path()); - dmesgln("VirtualFileSystem: mounted root from {} ({})", fs.class_name(), pseudo_path); + dmesgln("VirtualFileSystem: mounted root({}) from {} ({})", fs.fsid(), fs.class_name(), pseudo_path); + // Note: Actually add a mount for the filesystem and increment the filesystem mounted count m_mounts.with([&](auto& mounts) { + new_mount->guest_fs().mounted_count({}).with([&](auto& mounted_count) { + mounted_count++; + }); mounts.append(move(new_mount)); }); @@ -241,6 +258,24 @@ ErrorOr VirtualFileSystem::lookup_metadata(Credentials const& cre return custody->inode().metadata(); } +ErrorOr> VirtualFileSystem::find_already_existing_or_create_file_backed_file_system(OpenFileDescription& description, Function>(OpenFileDescription&)> callback) +{ + return TRY(m_file_backed_file_systems_list.with([&](auto& list) -> ErrorOr> { + for (auto& node : list) { + if (&node.file_description() == &description) { + return node; + } + if (&node.file() == &description.file()) { + return node; + } + } + auto fs = TRY(callback(description)); + VERIFY(fs->is_file_backed()); + list.append(static_cast(*fs)); + return static_ptr_cast(fs); + })); +} + ErrorOr> VirtualFileSystem::open(Credentials const& credentials, StringView path, int options, mode_t mode, Custody& base, Optional owner) { if ((options & O_CREAT) && (options & O_DIRECTORY)) diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 75094b4b1b..514217e1e1 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -48,7 +50,7 @@ public: ErrorOr mount(FileSystem&, Custody& mount_point, int flags); ErrorOr bind_mount(Custody& source, Custody& mount_point, int flags); ErrorOr remount(Custody& mount_point, int new_flags); - ErrorOr unmount(Inode& guest_inode); + ErrorOr unmount(Custody& mount_point); ErrorOr> open(Credentials const&, StringView path, int options, mode_t mode, Custody& base, Optional = {}); ErrorOr> create(Credentials const&, StringView path, int options, mode_t mode, Custody& parent_custody, Optional = {}); @@ -71,6 +73,8 @@ public: ErrorOr for_each_mount(Function(Mount const&)>) const; + ErrorOr> find_already_existing_or_create_file_backed_file_system(OpenFileDescription& description, Function>(OpenFileDescription&)> callback); + InodeIdentifier root_inode_id() const; static void sync(); @@ -101,6 +105,7 @@ private: SpinlockProtected> m_root_custody; SpinlockProtected, 16>> m_mounts { LockRank::None }; + SpinlockProtected> m_file_backed_file_systems_list { LockRank::None }; }; } diff --git a/Kernel/Syscalls/mount.cpp b/Kernel/Syscalls/mount.cpp index 4b1f306dcf..a97425ee40 100644 --- a/Kernel/Syscalls/mount.cpp +++ b/Kernel/Syscalls/mount.cpp @@ -39,7 +39,7 @@ static constexpr FileSystemInitializer s_initializers[] = { { "fat"sv, "FATFS"sv, true, true, true, FATFS::try_create, {} }, }; -static ErrorOr> create_filesystem_instance(StringView fs_type, OpenFileDescription* possible_description) +static ErrorOr> find_or_create_filesystem_instance(StringView fs_type, OpenFileDescription* possible_description) { for (auto& initializer_entry : s_initializers) { if (fs_type != initializer_entry.short_name && fs_type != initializer_entry.name) @@ -49,6 +49,9 @@ static ErrorOr> create_filesystem_instance(StringV NonnullLockRefPtr fs = TRY(initializer_entry.create()); return fs; } + // Note: If there's an associated file description with the filesystem, we could + // try to first find it from the VirtualFileSystem filesystem list and if it was not found, + // then create it and add it. VERIFY(initializer_entry.create_with_fd); if (!possible_description) return EBADF; @@ -60,8 +63,7 @@ static ErrorOr> create_filesystem_instance(StringV dbgln("mount: this is not a seekable file"); return ENODEV; } - NonnullLockRefPtr fs = TRY(initializer_entry.create_with_fd(description)); - return fs; + return TRY(VirtualFileSystem::the().find_already_existing_or_create_file_backed_file_system(description, initializer_entry.create_with_fd)); } return ENODEV; } @@ -112,11 +114,11 @@ ErrorOr Process::sys$mount(Userspace u if (!description_or_error.is_error()) { auto description = description_or_error.release_value(); - fs = TRY(create_filesystem_instance(fs_type, description.ptr())); + fs = TRY(find_or_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, {})); + fs = TRY(find_or_create_filesystem_instance(fs_type, {})); } TRY(fs->initialize()); @@ -135,8 +137,7 @@ ErrorOr Process::sys$umount(Userspace user_mountpoint, siz auto mountpoint = TRY(get_syscall_path_argument(user_mountpoint, mountpoint_length)); auto custody = TRY(VirtualFileSystem::the().resolve_path(credentials, mountpoint->view(), current_directory())); - auto& guest_inode = custody->inode(); - TRY(VirtualFileSystem::the().unmount(guest_inode)); + TRY(VirtualFileSystem::the().unmount(*custody)); return 0; }