summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/FileSystem/BlockBasedFileSystem.cpp18
-rw-r--r--Kernel/FileSystem/BlockBasedFileSystem.h2
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.cpp23
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.h2
-rw-r--r--Kernel/FileSystem/FileSystem.cpp32
-rw-r--r--Kernel/FileSystem/FileSystem.h13
-rw-r--r--Kernel/FileSystem/ISO9660FileSystem.cpp1
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.cpp62
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.h4
9 files changed, 103 insertions, 54 deletions
diff --git a/Kernel/FileSystem/BlockBasedFileSystem.cpp b/Kernel/FileSystem/BlockBasedFileSystem.cpp
index b343022ecf..4e78a5d3ed 100644
--- a/Kernel/FileSystem/BlockBasedFileSystem.cpp
+++ b/Kernel/FileSystem/BlockBasedFileSystem.cpp
@@ -27,7 +27,7 @@ public:
, m_entries(move(entries_buffer))
{
for (size_t i = 0; i < EntryCount; ++i) {
- entries()[i].data = m_cached_block_data->data() + i * m_fs.block_size();
+ entries()[i].data = m_cached_block_data->data() + i * m_fs->block_size();
m_clean_list.append(entries()[i]);
}
}
@@ -72,7 +72,7 @@ public:
// Not a single clean entry! Flush writes and try again.
// NOTE: We want to make sure we only call FileBackedFileSystem flush here,
// not some FileBackedFileSystem subclass flush!
- m_fs.flush_writes_impl();
+ m_fs->flush_writes_impl();
return ensure(block_index);
}
@@ -100,10 +100,10 @@ public:
}
private:
- BlockBasedFileSystem& m_fs;
- mutable HashMap<BlockBasedFileSystem::BlockIndex, CacheEntry*> m_hash;
- mutable IntrusiveList<&CacheEntry::list_node> m_clean_list;
+ mutable NonnullRefPtr<BlockBasedFileSystem> m_fs;
mutable IntrusiveList<&CacheEntry::list_node> m_dirty_list;
+ mutable IntrusiveList<&CacheEntry::list_node> m_clean_list;
+ mutable HashMap<BlockBasedFileSystem::BlockIndex, CacheEntry*> m_hash;
NonnullOwnPtr<KBuffer> m_cached_block_data;
NonnullOwnPtr<KBuffer> m_entries;
};
@@ -116,6 +116,14 @@ BlockBasedFileSystem::BlockBasedFileSystem(OpenFileDescription& file_description
BlockBasedFileSystem::~BlockBasedFileSystem() = default;
+void BlockBasedFileSystem::remove_disk_cache_before_last_unmount()
+{
+ VERIFY(m_lock.is_locked());
+ m_cache.with_exclusive([&](auto& cache) {
+ cache.clear();
+ });
+}
+
ErrorOr<void> BlockBasedFileSystem::initialize_while_locked()
{
VERIFY(m_lock.is_locked());
diff --git a/Kernel/FileSystem/BlockBasedFileSystem.h b/Kernel/FileSystem/BlockBasedFileSystem.h
index 817747a482..58893d5e10 100644
--- a/Kernel/FileSystem/BlockBasedFileSystem.h
+++ b/Kernel/FileSystem/BlockBasedFileSystem.h
@@ -41,6 +41,8 @@ protected:
u64 m_logical_block_size { 512 };
+ void remove_disk_cache_before_last_unmount();
+
private:
DiskCache& cache() const;
void flush_specific_block_if_needed(BlockIndex index);
diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp
index e36f63e5f5..15aa39c1e2 100644
--- a/Kernel/FileSystem/Ext2FileSystem.cpp
+++ b/Kernel/FileSystem/Ext2FileSystem.cpp
@@ -140,7 +140,7 @@ ErrorOr<void> Ext2FS::initialize_while_locked()
}
}
- m_root_inode = static_ptr_cast<Ext2FSInode>(TRY(get_inode({ fsid(), EXT2_ROOT_INO })));
+ m_root_inode = TRY(build_root_inode());
return {};
}
@@ -770,10 +770,29 @@ ErrorOr<void> Ext2FSInode::flush_metadata()
return {};
}
+ErrorOr<NonnullLockRefPtr<Ext2FSInode>> Ext2FS::build_root_inode() const
+{
+ MutexLocker locker(m_lock);
+ BlockIndex block_index;
+ unsigned offset;
+ if (!find_block_containing_inode(EXT2_ROOT_INO, block_index, offset))
+ return EINVAL;
+
+ auto inode = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Ext2FSInode(const_cast<Ext2FS&>(*this), EXT2_ROOT_INO)));
+
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<u8*>(&inode->m_raw_inode));
+ TRY(read_block(block_index, &buffer, sizeof(ext2_inode), offset));
+ return inode;
+}
+
ErrorOr<NonnullLockRefPtr<Inode>> Ext2FS::get_inode(InodeIdentifier inode) const
{
MutexLocker locker(m_lock);
VERIFY(inode.fsid() == fsid());
+ VERIFY(m_root_inode);
+
+ if (inode.index() == EXT2_ROOT_INO)
+ return *m_root_inode;
{
auto it = m_inode_cache.find(inode.index());
@@ -1690,12 +1709,12 @@ unsigned Ext2FS::free_inode_count() const
ErrorOr<void> Ext2FS::prepare_to_clear_last_mount()
{
MutexLocker locker(m_lock);
-
for (auto& it : m_inode_cache) {
if (it.value->ref_count() > 1)
return EBUSY;
}
+ BlockBasedFileSystem::remove_disk_cache_before_last_unmount();
m_inode_cache.clear();
m_root_inode = nullptr;
return {};
diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h
index 9d22d04a42..88bcf278c3 100644
--- a/Kernel/FileSystem/Ext2FileSystem.h
+++ b/Kernel/FileSystem/Ext2FileSystem.h
@@ -118,6 +118,8 @@ private:
u64 blocks_per_group() const;
u64 inode_size() const;
+ ErrorOr<NonnullLockRefPtr<Ext2FSInode>> build_root_inode() const;
+
ErrorOr<void> write_ext2_inode(InodeIndex, ext2_inode const&);
bool find_block_containing_inode(InodeIndex, BlockIndex& block_index, unsigned& offset) const;
diff --git a/Kernel/FileSystem/FileSystem.cpp b/Kernel/FileSystem/FileSystem.cpp
index 09f3bfc143..47d88ef485 100644
--- a/Kernel/FileSystem/FileSystem.cpp
+++ b/Kernel/FileSystem/FileSystem.cpp
@@ -9,6 +9,7 @@
#include <AK/StringView.h>
#include <Kernel/FileSystem/FileSystem.h>
#include <Kernel/FileSystem/Inode.h>
+#include <Kernel/FileSystem/VirtualFileSystem.h>
#include <Kernel/InterruptDisabler.h>
#include <Kernel/Memory/MemoryManager.h>
#include <Kernel/Net/LocalSocket.h>
@@ -16,30 +17,14 @@
namespace Kernel {
static u32 s_lastFileSystemID;
-static Singleton<HashMap<FileSystemID, FileSystem*>> s_file_system_map;
-
-static HashMap<FileSystemID, FileSystem*>& all_file_systems()
-{
- return *s_file_system_map;
-}
FileSystem::FileSystem()
: m_fsid(++s_lastFileSystemID)
{
- s_file_system_map->set(m_fsid, this);
}
FileSystem::~FileSystem()
{
- s_file_system_map->remove(m_fsid);
-}
-
-FileSystem* FileSystem::from_fsid(FileSystemID id)
-{
- auto it = all_file_systems().find(id);
- if (it != all_file_systems().end())
- return (*it).value;
- return nullptr;
}
ErrorOr<void> FileSystem::prepare_to_unmount()
@@ -61,23 +46,12 @@ FileSystem::DirectoryEntryView::DirectoryEntryView(StringView n, InodeIdentifier
void FileSystem::sync()
{
Inode::sync_all();
-
- NonnullLockRefPtrVector<FileSystem, 32> file_systems;
- {
- InterruptDisabler disabler;
- for (auto& it : all_file_systems())
- file_systems.append(*it.value);
- }
-
- for (auto& fs : file_systems)
- fs.flush_writes();
+ VirtualFileSystem::the().sync_filesystems();
}
void FileSystem::lock_all()
{
- for (auto& it : all_file_systems()) {
- it.value->m_lock.lock();
- }
+ VirtualFileSystem::the().lock_all_filesystems();
}
}
diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h
index 4098884062..39ae416ca6 100644
--- a/Kernel/FileSystem/FileSystem.h
+++ b/Kernel/FileSystem/FileSystem.h
@@ -20,12 +20,12 @@ namespace Kernel {
class FileSystem : public AtomicRefCounted<FileSystem> {
friend class Inode;
+ friend class VirtualFileSystem;
public:
virtual ~FileSystem();
FileSystemID fsid() const { return m_fsid; }
- static FileSystem* from_fsid(FileSystemID);
static void sync();
static void lock_all();
@@ -80,18 +80,9 @@ private:
bool m_readonly { false };
SpinlockProtected<size_t> m_attach_count { LockRank::FileSystem, 0 };
+ IntrusiveListNode<FileSystem> m_file_system_node;
};
-inline FileSystem* InodeIdentifier::fs() // NOLINT(readability-make-member-function-const) const InodeIdentifiers should not be able to modify the FileSystem
-{
- return FileSystem::from_fsid(m_fsid);
-}
-
-inline FileSystem const* InodeIdentifier::fs() const
-{
- return FileSystem::from_fsid(m_fsid);
-}
-
}
namespace AK {
diff --git a/Kernel/FileSystem/ISO9660FileSystem.cpp b/Kernel/FileSystem/ISO9660FileSystem.cpp
index 3061f868a8..e9fd2bc448 100644
--- a/Kernel/FileSystem/ISO9660FileSystem.cpp
+++ b/Kernel/FileSystem/ISO9660FileSystem.cpp
@@ -235,6 +235,7 @@ u8 ISO9660FS::internal_file_type_to_directory_entry_type(DirectoryEntryView cons
ErrorOr<void> ISO9660FS::prepare_to_clear_last_mount()
{
// FIXME: Do proper cleaning here.
+ BlockBasedFileSystem::remove_disk_cache_before_last_unmount();
return {};
}
diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp
index 3d1f11bcc5..6fe7161b12 100644
--- a/Kernel/FileSystem/VirtualFileSystem.cpp
+++ b/Kernel/FileSystem/VirtualFileSystem.cpp
@@ -111,6 +111,30 @@ ErrorOr<void> VirtualFileSystem::remount(Custody& mount_point, int new_flags)
return {};
}
+void VirtualFileSystem::sync_filesystems()
+{
+ NonnullLockRefPtrVector<FileSystem, 32> file_systems;
+ m_file_systems_list.with([&](auto const& list) {
+ for (auto& fs : list)
+ file_systems.append(fs);
+ });
+
+ for (auto& fs : file_systems)
+ fs.flush_writes();
+}
+
+void VirtualFileSystem::lock_all_filesystems()
+{
+ NonnullLockRefPtrVector<FileSystem, 32> file_systems;
+ m_file_systems_list.with([&](auto const& list) {
+ for (auto& fs : list)
+ file_systems.append(fs);
+ });
+
+ for (auto& fs : file_systems)
+ fs.m_lock.lock();
+}
+
ErrorOr<void> VirtualFileSystem::unmount(Custody& mountpoint_custody)
{
auto& guest_inode = mountpoint_custody.inode();
@@ -125,11 +149,27 @@ ErrorOr<void> VirtualFileSystem::unmount(Custody& mountpoint_custody)
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--;
+ NonnullRefPtr<FileSystem> fs = mount->guest_fs();
+ TRY(fs->prepare_to_unmount());
+ fs->mounted_count({}).with([&](auto& mounted_count) {
+ VERIFY(mounted_count > 0);
+ if (mounted_count == 1) {
+ dbgln("VirtualFileSystem: Unmounting file system {} for the last time...", fs->fsid());
+ m_file_systems_list.with([&](auto& list) {
+ list.remove(*fs);
+ });
+ if (fs->is_file_backed()) {
+ dbgln("VirtualFileSystem: Unmounting file backed file system {} for the last time...", fs->fsid());
+ auto& file_backed_fs = static_cast<FileBackedFileSystem&>(*fs);
+ m_file_backed_file_systems_list.with([&](auto& list) {
+ list.remove(file_backed_fs);
+ });
+ }
+ } else {
+ mounted_count--;
+ }
});
- dbgln("VirtualFileSystem: Unmounting file system {}...", mount->guest_fs().fsid());
+ dbgln("VirtualFileSystem: Unmounting file system {}...", fs->fsid());
(void)mounts.unstable_take(i);
return {};
}
@@ -154,15 +194,20 @@ ErrorOr<void> VirtualFileSystem::mount_root(FileSystem& fs)
}
m_root_inode = root_inode;
- auto pseudo_path = TRY(static_cast<FileBackedFileSystem&>(fs).file_description().pseudo_path());
- dmesgln("VirtualFileSystem: mounted root({}) from {} ({})", fs.fsid(), fs.class_name(), pseudo_path);
-
if (fs.is_file_backed()) {
+ auto pseudo_path = TRY(static_cast<FileBackedFileSystem&>(fs).file_description().pseudo_path());
+ dmesgln("VirtualFileSystem: mounted root({}) from {} ({})", fs.fsid(), fs.class_name(), pseudo_path);
m_file_backed_file_systems_list.with([&](auto& list) {
list.append(static_cast<FileBackedFileSystem&>(fs));
});
+ } else {
+ dmesgln("VirtualFileSystem: mounted root({}) from {}", fs.fsid(), fs.class_name());
}
+ m_file_systems_list.with([&](auto& fs_list) {
+ fs_list.append(fs);
+ });
+
// 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) {
@@ -278,6 +323,9 @@ ErrorOr<NonnullLockRefPtr<FileBackedFileSystem>> VirtualFileSystem::find_already
auto fs = TRY(callback(description));
VERIFY(fs->is_file_backed());
list.append(static_cast<FileBackedFileSystem&>(*fs));
+ m_file_systems_list.with([&](auto& fs_list) {
+ fs_list.append(*fs);
+ });
return static_ptr_cast<FileBackedFileSystem>(fs);
}));
}
diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h
index 514217e1e1..87decc58e5 100644
--- a/Kernel/FileSystem/VirtualFileSystem.h
+++ b/Kernel/FileSystem/VirtualFileSystem.h
@@ -77,6 +77,9 @@ public:
InodeIdentifier root_inode_id() const;
+ void sync_filesystems();
+ void lock_all_filesystems();
+
static void sync();
NonnullRefPtr<Custody> root_custody();
@@ -106,6 +109,7 @@ private:
SpinlockProtected<Vector<NonnullOwnPtr<Mount>, 16>> m_mounts { LockRank::None };
SpinlockProtected<IntrusiveList<&FileBackedFileSystem::m_file_backed_file_system_node>> m_file_backed_file_systems_list { LockRank::None };
+ SpinlockProtected<IntrusiveList<&FileSystem::m_file_system_node>> m_file_systems_list { LockRank::FileSystem };
};
}