mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:52:45 +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)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; | ||||
|  |  | |||
|  | @ -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<typename U> RetainPtr(RetainPtr<U>&& other) : m_ptr(static_cast<T*>(other.leakRef())) { } | ||||
|     ~RetainPtr() | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ public: | |||
|     { | ||||
|         ASSERT(m_retainCount); | ||||
|         if (!--m_retainCount) | ||||
|             delete static_cast<const T*>(this); | ||||
|             delete static_cast<T*>(this); | ||||
|     } | ||||
| 
 | ||||
|     int retainCount() const | ||||
|  |  | |||
|  | @ -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(); | ||||
| } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| #include "FileSystem.h" | ||||
| #include <AK/ByteBuffer.h> | ||||
| #include <AK/HashMap.h> | ||||
| #include <AK/Lock.h> | ||||
| 
 | ||||
| class DiskBackedFileSystem : public FileSystem { | ||||
| public: | ||||
|  | @ -28,5 +29,7 @@ protected: | |||
| private: | ||||
|     unsigned m_blockSize { 0 }; | ||||
|     RetainPtr<DiskDevice> m_device; | ||||
| 
 | ||||
|     mutable SpinLock m_blockCacheLock; | ||||
|     mutable HashMap<unsigned, ByteBuffer> m_blockCache; | ||||
| }; | ||||
|  |  | |||
|  | @ -11,6 +11,31 @@ | |||
| 
 | ||||
| //#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) | ||||
| { | ||||
|     return adopt(*new Ext2FileSystem(move(device))); | ||||
|  | @ -159,14 +184,22 @@ ByteBuffer Ext2FileSystem::readBlockContainingInode(unsigned inode, unsigned& bl | |||
|     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 offset; | ||||
|     auto block = readBlockContainingInode(inode, blockIndex, offset); | ||||
| 
 | ||||
|     if (!block) | ||||
|         return nullptr; | ||||
|         return { }; | ||||
| 
 | ||||
|     auto* e2inode = reinterpret_cast<ext2_inode*>(kmalloc(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); | ||||
| #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 | ||||
|  |  | |||
|  | @ -19,6 +19,8 @@ private: | |||
|     typedef unsigned BlockIndex; | ||||
|     typedef unsigned GroupIndex; | ||||
|     typedef unsigned InodeIndex; | ||||
|     class CachedExt2Inode; | ||||
|     class CachedExt2InodeImpl; | ||||
| 
 | ||||
|     explicit Ext2FileSystem(RetainPtr<DiskDevice>&&); | ||||
| 
 | ||||
|  | @ -30,7 +32,7 @@ private: | |||
|     unsigned blocksPerGroup() const; | ||||
|     unsigned inodeSize() const; | ||||
| 
 | ||||
|     OwnPtr<ext2_inode> 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<unsigned, RetainPtr<CachedExt2InodeImpl>> m_inodeCache; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling