summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-25 22:05:53 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-25 22:05:53 +0200
commit44673c4f3b092f03ed8607b743903cf03d46b3f2 (patch)
tree79edb1852b226da711099e32dd1c775c22710fd0 /Kernel/FileSystem
parente0cdc5db0df929e202b69ff8df9029a564ff7a3c (diff)
downloadserenity-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.cpp37
-rw-r--r--Kernel/FileSystem/DiskBackedFileSystem.h4
-rw-r--r--Kernel/FileSystem/FileSystem.cpp12
-rw-r--r--Kernel/FileSystem/FileSystem.h2
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();