diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-04-25 22:05:53 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-04-25 22:05:53 +0200 |
commit | 44673c4f3b092f03ed8607b743903cf03d46b3f2 (patch) | |
tree | 79edb1852b226da711099e32dd1c775c22710fd0 /Kernel/FileSystem | |
parent | e0cdc5db0df929e202b69ff8df9029a564ff7a3c (diff) | |
download | serenity-44673c4f3b092f03ed8607b743903cf03d46b3f2.zip |
Kernel: Add a write cache to DiskBackedFS.
This way you can spam small write()s on a file without the kernel writing
to disk every single time. Flushes are included in the FS::sync() operation
and will get triggered regularly by syncd. :^)
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r-- | Kernel/FileSystem/DiskBackedFileSystem.cpp | 37 | ||||
-rw-r--r-- | Kernel/FileSystem/DiskBackedFileSystem.h | 4 | ||||
-rw-r--r-- | Kernel/FileSystem/FileSystem.cpp | 12 | ||||
-rw-r--r-- | Kernel/FileSystem/FileSystem.h | 2 |
4 files changed, 42 insertions, 13 deletions
diff --git a/Kernel/FileSystem/DiskBackedFileSystem.cpp b/Kernel/FileSystem/DiskBackedFileSystem.cpp index f6214bb8b3..4d45aabc01 100644 --- a/Kernel/FileSystem/DiskBackedFileSystem.cpp +++ b/Kernel/FileSystem/DiskBackedFileSystem.cpp @@ -66,8 +66,10 @@ bool DiskBackedFS::write_block(unsigned index, const ByteBuffer& data) if (auto* cached_block = block_cache().resource().get({ fsid(), index })) cached_block->m_buffer = data; } - DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size()); - return device().write(base_offset, block_size(), data.pointer()); + + LOCKER(m_lock); + m_write_cache.set(index, data.isolated_copy()); + return true; } bool DiskBackedFS::write_blocks(unsigned index, unsigned count, const ByteBuffer& data) @@ -75,16 +77,9 @@ bool DiskBackedFS::write_blocks(unsigned index, unsigned count, const ByteBuffer #ifdef DBFS_DEBUG kprintf("DiskBackedFileSystem::write_blocks %u x%u\n", index, count); #endif - // FIXME: Maybe reorder this so we send out the write commands before updating cache? - { - LOCKER(block_cache().lock()); - for (unsigned i = 0; i < count; ++i) { - if (auto* cached_block = block_cache().resource().get({ fsid(), index + i })) - cached_block->m_buffer = data.slice(i * block_size(), block_size()); - } - } - DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size()); - return device().write(base_offset, count * block_size(), data.pointer()); + for (unsigned i = 0; i < count; ++i) + write_block(index + i, data.slice(i * block_size(), block_size())); + return true; } ByteBuffer DiskBackedFS::read_block(unsigned index) const @@ -92,6 +87,13 @@ ByteBuffer DiskBackedFS::read_block(unsigned index) const #ifdef DBFS_DEBUG kprintf("DiskBackedFileSystem::read_block %u\n", index); #endif + + { + LOCKER(m_lock); + if (auto it = m_write_cache.find(index); it != m_write_cache.end()) + return it->value; + } + { LOCKER(block_cache().lock()); if (auto* cached_block = block_cache().resource().get({ fsid(), index })) @@ -105,6 +107,7 @@ 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)); @@ -138,3 +141,13 @@ void DiskBackedFS::set_block_size(unsigned block_size) return; m_block_size = block_size; } + +void DiskBackedFS::flush_writes() +{ + LOCKER(m_lock); + for (auto& it : m_write_cache) { + DiskOffset base_offset = static_cast<DiskOffset>(it.key) * static_cast<DiskOffset>(block_size()); + device().write(base_offset, block_size(), it.value.data()); + } + m_write_cache.clear(); +} diff --git a/Kernel/FileSystem/DiskBackedFileSystem.h b/Kernel/FileSystem/DiskBackedFileSystem.h index 75d3f8f8fc..b115eb6d12 100644 --- a/Kernel/FileSystem/DiskBackedFileSystem.h +++ b/Kernel/FileSystem/DiskBackedFileSystem.h @@ -12,6 +12,8 @@ public: int block_size() const { return m_block_size; } + virtual void flush_writes() override; + protected: explicit DiskBackedFS(Retained<DiskDevice>&&); @@ -26,4 +28,6 @@ protected: private: int m_block_size { 0 }; Retained<DiskDevice> m_device; + + HashMap<unsigned, ByteBuffer> m_write_cache; }; diff --git a/Kernel/FileSystem/FileSystem.cpp b/Kernel/FileSystem/FileSystem.cpp index b3ec211785..c05884a0dc 100644 --- a/Kernel/FileSystem/FileSystem.cpp +++ b/Kernel/FileSystem/FileSystem.cpp @@ -144,7 +144,7 @@ int Inode::decrement_link_count() void FS::sync() { - Vector<Retained<Inode>> inodes; + Vector<Retained<Inode>, 32> inodes; { InterruptDisabler disabler; for (auto* inode : all_inodes()) { @@ -157,6 +157,16 @@ void FS::sync() ASSERT(inode->is_metadata_dirty()); inode->flush_metadata(); } + + Vector<Retained<FS>, 32> fses; + { + InterruptDisabler disabler; + for (auto& it : all_fses()) + fses.append(*it.value); + } + + for (auto fs : fses) + fs->flush_writes(); } void Inode::set_vmo(VMObject& vmo) diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h index 847c2280c3..abe31cdd11 100644 --- a/Kernel/FileSystem/FileSystem.h +++ b/Kernel/FileSystem/FileSystem.h @@ -57,6 +57,8 @@ public: virtual RetainPtr<Inode> get_inode(InodeIdentifier) const = 0; + virtual void flush_writes() { } + protected: FS(); |