From 7014daa2355d374c57ed09a4c55c460f0486d7f3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 10 Feb 2019 20:07:14 +0100 Subject: Kernel: Add an LRU block cache. This papers over some of the incredibly inefficient access patterns in the Ext2FS implementation for a while longer. :^) --- Kernel/DiskBackedFileSystem.cpp | 51 +++++++++++++++++++++++++++++++++++++++++ Kernel/FileSystem.h | 3 +-- 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'Kernel') diff --git a/Kernel/DiskBackedFileSystem.cpp b/Kernel/DiskBackedFileSystem.cpp index e28f18d4e9..638a5b817d 100644 --- a/Kernel/DiskBackedFileSystem.cpp +++ b/Kernel/DiskBackedFileSystem.cpp @@ -1,8 +1,49 @@ #include "DiskBackedFileSystem.h" #include "i386.h" +#include //#define DBFS_DEBUG +struct BlockIdentifier { + unsigned fsid { 0 }; + unsigned index { 0 }; + + bool operator==(const BlockIdentifier& other) const { return fsid == other.fsid && index == other.index; } +}; + +namespace AK { + +template<> +struct Traits { + static unsigned hash(const BlockIdentifier& block_id) { return pair_int_hash(block_id.fsid, block_id.index); } + static void dump(const BlockIdentifier& block_id) { kprintf("[block %02u:%08u]", block_id.fsid, block_id.index); } +}; + +} + +class CachedBlock : public InlineLinkedListNode { +public: + CachedBlock(const BlockIdentifier& block_id, const ByteBuffer& buffer) + : m_key(block_id) + , m_buffer(buffer) + { + } + + BlockIdentifier m_key; + CachedBlock* m_next { nullptr }; + CachedBlock* m_prev { nullptr }; + + ByteBuffer m_buffer; +}; + +Lockable>& block_cache() +{ + static Lockable>* s_cache; + if (!s_cache) + s_cache = new Lockable>; + return *s_cache; +} + DiskBackedFS::DiskBackedFS(RetainPtr&& device) : m_device(move(device)) { @@ -37,6 +78,12 @@ ByteBuffer DiskBackedFS::read_block(unsigned index) const #ifdef DBFS_DEBUG kprintf("DiskBackedFileSystem::read_block %u\n", index); #endif + { + LOCKER(block_cache().lock()); + if (auto* cached_block = block_cache().resource().get({ fsid(), index })) + return cached_block->m_buffer; + } + auto buffer = ByteBuffer::create_uninitialized(block_size()); //kprintf("created block buffer with size %u\n", block_size()); DiskOffset base_offset = static_cast(index) * static_cast(block_size()); @@ -44,6 +91,10 @@ ByteBuffer DiskBackedFS::read_block(unsigned index) const bool success = device().read(base_offset, block_size(), buffer_pointer); ASSERT(success); ASSERT(buffer.size() == block_size()); + { + LOCKER(block_cache().lock()); + block_cache().resource().put({ fsid(), index }, CachedBlock({ fsid(), index }, buffer)); + } return buffer; } diff --git a/Kernel/FileSystem.h b/Kernel/FileSystem.h index eab654ac51..a6564b0de9 100644 --- a/Kernel/FileSystem.h +++ b/Kernel/FileSystem.h @@ -147,8 +147,7 @@ namespace AK { template<> struct Traits { - // FIXME: This is a shitty hash. - static unsigned hash(const InodeIdentifier& inode) { return Traits::hash(inode.fsid()) + Traits::hash(inode.index()); } + static unsigned hash(const InodeIdentifier& inode) { return pair_int_hash(inode.fsid(), inode.index()); } static void dump(const InodeIdentifier& inode) { kprintf("%02u:%08u", inode.fsid(), inode.index()); } }; -- cgit v1.2.3