diff --git a/AK/Lock.h b/AK/Lock.h index 27c7a73c7f0..a4207a3bef9 100644 --- a/AK/Lock.h +++ b/AK/Lock.h @@ -36,6 +36,7 @@ public: void lock(const char* func = nullptr) { + (void)func; #ifdef DEBUG_LOCKS { InterruptDisabler dis; @@ -56,6 +57,7 @@ public: void unlock(const char* func = nullptr) { + (void)func; // barrier(); ASSERT(m_lock); m_lock = 0; diff --git a/AK/RetainPtr.h b/AK/RetainPtr.h index d234b45e91d..b2fc6c7d2a8 100644 --- a/AK/RetainPtr.h +++ b/AK/RetainPtr.h @@ -29,6 +29,7 @@ public: RetainPtr(T* ptr) : m_ptr(ptr) { retainIfNotNull(m_ptr); } RetainPtr(T& object) : m_ptr(&object) { m_ptr->retain(); } RetainPtr(AdoptTag, T& object) : m_ptr(&object) { } + RetainPtr(RetainPtr& other) : m_ptr(other.copyRef().leakRef()) { } RetainPtr(RetainPtr&& other) : m_ptr(other.leakRef()) { } template RetainPtr(RetainPtr&& other) : m_ptr(static_cast(other.leakRef())) { } ~RetainPtr() diff --git a/AK/Retainable.h b/AK/Retainable.h index cf4308520c3..32c4a9b7a08 100644 --- a/AK/Retainable.h +++ b/AK/Retainable.h @@ -17,7 +17,7 @@ public: { ASSERT(m_retainCount); if (!--m_retainCount) - delete static_cast(this); + delete static_cast(this); } int retainCount() const diff --git a/VirtualFileSystem/DiskBackedFileSystem.cpp b/VirtualFileSystem/DiskBackedFileSystem.cpp index 1651e328784..9cefbaacfd9 100644 --- a/VirtualFileSystem/DiskBackedFileSystem.cpp +++ b/VirtualFileSystem/DiskBackedFileSystem.cpp @@ -46,6 +46,7 @@ ByteBuffer DiskBackedFileSystem::readBlock(unsigned index) const #ifdef BLOCK_CACHE { + LOCKER(m_blockCacheLock); InterruptDisabler disabler; auto it = m_blockCache.find(index); if (it != m_blockCache.end()) { @@ -64,6 +65,7 @@ ByteBuffer DiskBackedFileSystem::readBlock(unsigned index) const #ifdef BLOCK_CACHE { + LOCKER(m_blockCacheLock); InterruptDisabler disabler; if (m_blockCache.size() >= 32) m_blockCache.removeOneRandomly(); @@ -103,6 +105,7 @@ void DiskBackedFileSystem::setBlockSize(unsigned blockSize) void DiskBackedFileSystem::invalidateCaches() { + LOCKER(m_blockCacheLock); InterruptDisabler disabler; m_blockCache.clear(); } diff --git a/VirtualFileSystem/DiskBackedFileSystem.h b/VirtualFileSystem/DiskBackedFileSystem.h index e986ffa2df5..47c33228375 100644 --- a/VirtualFileSystem/DiskBackedFileSystem.h +++ b/VirtualFileSystem/DiskBackedFileSystem.h @@ -3,6 +3,7 @@ #include "FileSystem.h" #include #include +#include class DiskBackedFileSystem : public FileSystem { public: @@ -28,5 +29,7 @@ protected: private: unsigned m_blockSize { 0 }; RetainPtr m_device; + + mutable SpinLock m_blockCacheLock; mutable HashMap m_blockCache; }; diff --git a/VirtualFileSystem/Ext2FileSystem.cpp b/VirtualFileSystem/Ext2FileSystem.cpp index 013d44604de..24c9bdd2bae 100644 --- a/VirtualFileSystem/Ext2FileSystem.cpp +++ b/VirtualFileSystem/Ext2FileSystem.cpp @@ -11,6 +11,31 @@ //#define EXT2_DEBUG +class Ext2FileSystem::CachedExt2InodeImpl : public Retainable { +public: + CachedExt2InodeImpl(OwnPtr&& e2i) : e2inode(move(e2i)) { } + ~CachedExt2InodeImpl() { } + OwnPtr e2inode; +}; + +class Ext2FileSystem::CachedExt2Inode { +public: + const ext2_inode* operator->() const { return ptr->e2inode.ptr(); } + const ext2_inode& operator*() const { return *ptr->e2inode; } + ext2_inode* operator->() { return ptr->e2inode.ptr(); } + ext2_inode& operator*() { return *ptr->e2inode; } + bool operator!() const { return !ptr; } + operator bool() const { return !!ptr; } + CachedExt2Inode() { } + explicit CachedExt2Inode(OwnPtr&& e2inode) + : ptr(adopt(*new CachedExt2InodeImpl(move(e2inode)))) + { } + explicit CachedExt2Inode(RetainPtr p) + : ptr(p) + { } + RetainPtr ptr; +}; + RetainPtr Ext2FileSystem::create(RetainPtr&& device) { return adopt(*new Ext2FileSystem(move(device))); @@ -159,14 +184,22 @@ ByteBuffer Ext2FileSystem::readBlockContainingInode(unsigned inode, unsigned& bl return readBlock(blockIndex); } -OwnPtr Ext2FileSystem::lookupExt2Inode(unsigned inode) const +auto Ext2FileSystem::lookupExt2Inode(unsigned inode) const -> CachedExt2Inode { + { + LOCKER(m_inodeCacheLock); + auto it = m_inodeCache.find(inode); + if (it != m_inodeCache.end()) { + return CachedExt2Inode{ (*it).value }; + } + } + unsigned blockIndex; unsigned offset; auto block = readBlockContainingInode(inode, blockIndex, offset); if (!block) - return nullptr; + return { }; auto* e2inode = reinterpret_cast(kmalloc(inodeSize())); memcpy(e2inode, reinterpret_cast(block.offsetPointer(offset)), inodeSize()); @@ -174,7 +207,12 @@ OwnPtr Ext2FileSystem::lookupExt2Inode(unsigned inode) const dumpExt2Inode(*e2inode); #endif - return OwnPtr(e2inode); + LOCKER(m_inodeCacheLock); + if (m_inodeCache.size() >= 64) + m_inodeCache.removeOneRandomly(); + auto cachedInode = adopt(*new CachedExt2InodeImpl(OwnPtr(e2inode))); + m_inodeCache.set(inode, cachedInode.copyRef()); + return CachedExt2Inode{ cachedInode }; } InodeMetadata Ext2FileSystem::inodeMetadata(InodeIdentifier inode) const diff --git a/VirtualFileSystem/Ext2FileSystem.h b/VirtualFileSystem/Ext2FileSystem.h index 8d67959251f..9d355e000a6 100644 --- a/VirtualFileSystem/Ext2FileSystem.h +++ b/VirtualFileSystem/Ext2FileSystem.h @@ -19,6 +19,8 @@ private: typedef unsigned BlockIndex; typedef unsigned GroupIndex; typedef unsigned InodeIndex; + class CachedExt2Inode; + class CachedExt2InodeImpl; explicit Ext2FileSystem(RetainPtr&&); @@ -30,7 +32,7 @@ private: unsigned blocksPerGroup() const; unsigned inodeSize() const; - OwnPtr lookupExt2Inode(unsigned) const; + CachedExt2Inode lookupExt2Inode(unsigned) const; bool writeExt2Inode(unsigned, const ext2_inode&); ByteBuffer readBlockContainingInode(unsigned inode, unsigned& blockIndex, unsigned& offset) const; @@ -72,5 +74,8 @@ private: mutable ByteBuffer m_cachedSuperBlock; mutable ByteBuffer m_cachedBlockGroupDescriptorTable; + + mutable SpinLock m_inodeCacheLock; + mutable HashMap> m_inodeCache; };