Parcourir la source

Add an inode metadata cache to the ext2fs implementation.

Andreas Kling il y a 6 ans
Parent
commit
8e640539ef

+ 2 - 0
AK/Lock.h

@@ -36,6 +36,7 @@ public:
 
 
     void lock(const char* func = nullptr)
     void lock(const char* func = nullptr)
     {
     {
+        (void)func;
 #ifdef DEBUG_LOCKS
 #ifdef DEBUG_LOCKS
         {
         {
             InterruptDisabler dis;
             InterruptDisabler dis;
@@ -56,6 +57,7 @@ public:
 
 
     void unlock(const char* func = nullptr)
     void unlock(const char* func = nullptr)
     {
     {
+        (void)func;
         // barrier();
         // barrier();
         ASSERT(m_lock);
         ASSERT(m_lock);
         m_lock = 0;
         m_lock = 0;

+ 1 - 0
AK/RetainPtr.h

@@ -29,6 +29,7 @@ public:
     RetainPtr(T* ptr) : m_ptr(ptr) { retainIfNotNull(m_ptr); }
     RetainPtr(T* ptr) : m_ptr(ptr) { retainIfNotNull(m_ptr); }
     RetainPtr(T& object) : m_ptr(&object) { m_ptr->retain(); }
     RetainPtr(T& object) : m_ptr(&object) { m_ptr->retain(); }
     RetainPtr(AdoptTag, T& object) : m_ptr(&object) { }
     RetainPtr(AdoptTag, T& object) : m_ptr(&object) { }
+    RetainPtr(RetainPtr& other) : m_ptr(other.copyRef().leakRef()) { }
     RetainPtr(RetainPtr&& other) : m_ptr(other.leakRef()) { }
     RetainPtr(RetainPtr&& other) : m_ptr(other.leakRef()) { }
     template<typename U> RetainPtr(RetainPtr<U>&& other) : m_ptr(static_cast<T*>(other.leakRef())) { }
     template<typename U> RetainPtr(RetainPtr<U>&& other) : m_ptr(static_cast<T*>(other.leakRef())) { }
     ~RetainPtr()
     ~RetainPtr()

+ 1 - 1
AK/Retainable.h

@@ -17,7 +17,7 @@ public:
     {
     {
         ASSERT(m_retainCount);
         ASSERT(m_retainCount);
         if (!--m_retainCount)
         if (!--m_retainCount)
-            delete static_cast<const T*>(this);
+            delete static_cast<T*>(this);
     }
     }
 
 
     int retainCount() const
     int retainCount() const

+ 3 - 0
VirtualFileSystem/DiskBackedFileSystem.cpp

@@ -46,6 +46,7 @@ ByteBuffer DiskBackedFileSystem::readBlock(unsigned index) const
 
 
 #ifdef BLOCK_CACHE
 #ifdef BLOCK_CACHE
     {
     {
+        LOCKER(m_blockCacheLock);
         InterruptDisabler disabler;
         InterruptDisabler disabler;
         auto it = m_blockCache.find(index);
         auto it = m_blockCache.find(index);
         if (it != m_blockCache.end()) {
         if (it != m_blockCache.end()) {
@@ -64,6 +65,7 @@ ByteBuffer DiskBackedFileSystem::readBlock(unsigned index) const
 
 
 #ifdef BLOCK_CACHE
 #ifdef BLOCK_CACHE
     {
     {
+        LOCKER(m_blockCacheLock);
         InterruptDisabler disabler;
         InterruptDisabler disabler;
         if (m_blockCache.size() >= 32)
         if (m_blockCache.size() >= 32)
             m_blockCache.removeOneRandomly();
             m_blockCache.removeOneRandomly();
@@ -103,6 +105,7 @@ void DiskBackedFileSystem::setBlockSize(unsigned blockSize)
 
 
 void DiskBackedFileSystem::invalidateCaches()
 void DiskBackedFileSystem::invalidateCaches()
 {
 {
+    LOCKER(m_blockCacheLock);
     InterruptDisabler disabler;
     InterruptDisabler disabler;
     m_blockCache.clear();
     m_blockCache.clear();
 }
 }

+ 3 - 0
VirtualFileSystem/DiskBackedFileSystem.h

@@ -3,6 +3,7 @@
 #include "FileSystem.h"
 #include "FileSystem.h"
 #include <AK/ByteBuffer.h>
 #include <AK/ByteBuffer.h>
 #include <AK/HashMap.h>
 #include <AK/HashMap.h>
+#include <AK/Lock.h>
 
 
 class DiskBackedFileSystem : public FileSystem {
 class DiskBackedFileSystem : public FileSystem {
 public:
 public:
@@ -28,5 +29,7 @@ protected:
 private:
 private:
     unsigned m_blockSize { 0 };
     unsigned m_blockSize { 0 };
     RetainPtr<DiskDevice> m_device;
     RetainPtr<DiskDevice> m_device;
+
+    mutable SpinLock m_blockCacheLock;
     mutable HashMap<unsigned, ByteBuffer> m_blockCache;
     mutable HashMap<unsigned, ByteBuffer> m_blockCache;
 };
 };

+ 41 - 3
VirtualFileSystem/Ext2FileSystem.cpp

@@ -11,6 +11,31 @@
 
 
 //#define EXT2_DEBUG
 //#define EXT2_DEBUG
 
 
+class Ext2FileSystem::CachedExt2InodeImpl : public Retainable<CachedExt2InodeImpl> {
+public:
+    CachedExt2InodeImpl(OwnPtr<ext2_inode>&& e2i) : e2inode(move(e2i)) { }
+    ~CachedExt2InodeImpl() { }
+    OwnPtr<ext2_inode> 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<ext2_inode>&& e2inode)
+        : ptr(adopt(*new CachedExt2InodeImpl(move(e2inode))))
+    { }
+    explicit CachedExt2Inode(RetainPtr<CachedExt2InodeImpl> p)
+        : ptr(p)
+    { }
+    RetainPtr<CachedExt2InodeImpl> ptr;
+};
+
 RetainPtr<Ext2FileSystem> Ext2FileSystem::create(RetainPtr<DiskDevice>&& device)
 RetainPtr<Ext2FileSystem> Ext2FileSystem::create(RetainPtr<DiskDevice>&& device)
 {
 {
     return adopt(*new Ext2FileSystem(move(device)));
     return adopt(*new Ext2FileSystem(move(device)));
@@ -159,14 +184,22 @@ ByteBuffer Ext2FileSystem::readBlockContainingInode(unsigned inode, unsigned& bl
     return readBlock(blockIndex);
     return readBlock(blockIndex);
 }
 }
 
 
-OwnPtr<ext2_inode> 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 blockIndex;
     unsigned offset;
     unsigned offset;
     auto block = readBlockContainingInode(inode, blockIndex, offset);
     auto block = readBlockContainingInode(inode, blockIndex, offset);
 
 
     if (!block)
     if (!block)
-        return nullptr;
+        return { };
 
 
     auto* e2inode = reinterpret_cast<ext2_inode*>(kmalloc(inodeSize()));
     auto* e2inode = reinterpret_cast<ext2_inode*>(kmalloc(inodeSize()));
     memcpy(e2inode, reinterpret_cast<ext2_inode*>(block.offsetPointer(offset)), inodeSize());
     memcpy(e2inode, reinterpret_cast<ext2_inode*>(block.offsetPointer(offset)), inodeSize());
@@ -174,7 +207,12 @@ OwnPtr<ext2_inode> Ext2FileSystem::lookupExt2Inode(unsigned inode) const
     dumpExt2Inode(*e2inode);
     dumpExt2Inode(*e2inode);
 #endif
 #endif
 
 
-    return OwnPtr<ext2_inode>(e2inode);
+    LOCKER(m_inodeCacheLock);
+    if (m_inodeCache.size() >= 64)
+        m_inodeCache.removeOneRandomly();
+    auto cachedInode = adopt(*new CachedExt2InodeImpl(OwnPtr<ext2_inode>(e2inode)));
+    m_inodeCache.set(inode, cachedInode.copyRef());
+    return CachedExt2Inode{ cachedInode };
 }
 }
 
 
 InodeMetadata Ext2FileSystem::inodeMetadata(InodeIdentifier inode) const
 InodeMetadata Ext2FileSystem::inodeMetadata(InodeIdentifier inode) const

+ 6 - 1
VirtualFileSystem/Ext2FileSystem.h

@@ -19,6 +19,8 @@ private:
     typedef unsigned BlockIndex;
     typedef unsigned BlockIndex;
     typedef unsigned GroupIndex;
     typedef unsigned GroupIndex;
     typedef unsigned InodeIndex;
     typedef unsigned InodeIndex;
+    class CachedExt2Inode;
+    class CachedExt2InodeImpl;
 
 
     explicit Ext2FileSystem(RetainPtr<DiskDevice>&&);
     explicit Ext2FileSystem(RetainPtr<DiskDevice>&&);
 
 
@@ -30,7 +32,7 @@ private:
     unsigned blocksPerGroup() const;
     unsigned blocksPerGroup() const;
     unsigned inodeSize() const;
     unsigned inodeSize() const;
 
 
-    OwnPtr<ext2_inode> lookupExt2Inode(unsigned) const;
+    CachedExt2Inode lookupExt2Inode(unsigned) const;
     bool writeExt2Inode(unsigned, const ext2_inode&);
     bool writeExt2Inode(unsigned, const ext2_inode&);
     ByteBuffer readBlockContainingInode(unsigned inode, unsigned& blockIndex, unsigned& offset) const;
     ByteBuffer readBlockContainingInode(unsigned inode, unsigned& blockIndex, unsigned& offset) const;
 
 
@@ -72,5 +74,8 @@ private:
 
 
     mutable ByteBuffer m_cachedSuperBlock;
     mutable ByteBuffer m_cachedSuperBlock;
     mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
     mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
+
+    mutable SpinLock m_inodeCacheLock;
+    mutable HashMap<unsigned, RetainPtr<CachedExt2InodeImpl>> m_inodeCache;
 };
 };