mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:48:12 +00:00
Add an inode metadata cache to the ext2fs implementation.
This commit is contained in:
parent
4259ffb080
commit
8e640539ef
7 changed files with 57 additions and 5 deletions
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue