diff --git a/Kernel/FileSystem/BlockBasedFileSystem.cpp b/Kernel/FileSystem/BlockBasedFileSystem.cpp index 9cab1aef4b..92b25609d5 100644 --- a/Kernel/FileSystem/BlockBasedFileSystem.cpp +++ b/Kernel/FileSystem/BlockBasedFileSystem.cpp @@ -35,6 +35,7 @@ public: ~DiskCache() = default; bool is_dirty() const { return !m_dirty_list.is_empty(); } + bool entry_is_dirty(CacheEntry const& entry) const { return m_dirty_list.contains(entry); } void mark_all_clean() { @@ -52,13 +53,20 @@ public: m_clean_list.prepend(entry); } + CacheEntry* get(BlockBasedFileSystem::BlockIndex block_index) const + { + auto it = m_hash.find(block_index); + if (it == m_hash.end()) + return nullptr; + auto& entry = const_cast(*it->value); + VERIFY(entry.block_index == block_index); + return &entry; + } + CacheEntry& ensure(BlockBasedFileSystem::BlockIndex block_index) const { - if (auto it = m_hash.find(block_index); it != m_hash.end()) { - auto& entry = const_cast(*it->value); - VERIFY(entry.block_index == block_index); - return entry; - } + if (auto* entry = get(block_index)) + return *entry; if (m_clean_list.is_empty()) { // Not a single clean entry! Flush writes and try again. @@ -261,19 +269,14 @@ void BlockBasedFileSystem::flush_specific_block_if_needed(BlockIndex index) m_cache.with_exclusive([&](auto& cache) { if (!cache->is_dirty()) return; - Vector cleaned_entries; - cache->for_each_dirty_entry([&](CacheEntry& entry) { - if (entry.block_index != index) { - size_t base_offset = entry.block_index.value() * block_size(); - auto entry_data_buffer = UserOrKernelBuffer::for_kernel_buffer(entry.data); - [[maybe_unused]] auto rc = file_description().write(base_offset, entry_data_buffer, block_size()); - cleaned_entries.append(&entry); - } - }); - // NOTE: We make a separate pass to mark entries clean since marking them clean - // moves them out of the dirty list which would disturb the iteration above. - for (auto* entry : cleaned_entries) - cache->mark_clean(*entry); + auto* entry = cache->get(index); + if (!entry) + return; + if (!cache->entry_is_dirty(*entry)) + return; + size_t base_offset = entry->block_index.value() * block_size(); + auto entry_data_buffer = UserOrKernelBuffer::for_kernel_buffer(entry->data); + (void)file_description().write(base_offset, entry_data_buffer, block_size()); }); }