summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r--Kernel/FileSystem/BlockBasedFileSystem.cpp12
1 files changed, 11 insertions, 1 deletions
diff --git a/Kernel/FileSystem/BlockBasedFileSystem.cpp b/Kernel/FileSystem/BlockBasedFileSystem.cpp
index 2b329a7b9b..cf2916d3d1 100644
--- a/Kernel/FileSystem/BlockBasedFileSystem.cpp
+++ b/Kernel/FileSystem/BlockBasedFileSystem.cpp
@@ -133,6 +133,16 @@ ErrorOr<void> BlockBasedFileSystem::write_block(BlockIndex index, const UserOrKe
VERIFY(offset + count <= block_size());
dbgln_if(BBFS_DEBUG, "BlockBasedFileSystem::write_block {}, size={}", index, count);
+ // NOTE: We copy the `data` to write into a local buffer before taking the cache lock.
+ // This makes sure any page faults caused by accessing the data will occur before
+ // we tie down the cache.
+ auto buffered_data_or_error = ByteBuffer::create_uninitialized(count);
+ if (!buffered_data_or_error.has_value())
+ return ENOMEM;
+ auto buffered_data = buffered_data_or_error.release_value();
+
+ TRY(data.read(buffered_data.bytes()));
+
return m_cache.with_exclusive([&](auto& cache) -> ErrorOr<void> {
if (!allow_cache) {
flush_specific_block_if_needed(index);
@@ -147,7 +157,7 @@ ErrorOr<void> BlockBasedFileSystem::write_block(BlockIndex index, const UserOrKe
// Fill the cache first.
TRY(read_block(index, nullptr, block_size()));
}
- TRY(data.read(entry.data + offset, count));
+ memcpy(entry.data + offset, buffered_data.data(), count);
cache->mark_dirty(entry);
entry.has_data = true;