summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem/Ext2FileSystem.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-07-16 02:39:41 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-16 02:40:53 +0200
commit41c0009f6d3db0f1a8baecbabc65c2464534dd31 (patch)
treee8a36d656e86fde6b71b3df058dfd097a5d92bee /Kernel/FileSystem/Ext2FileSystem.cpp
parentabbd237ec174b3cd9138b65b28d40cdad62f50f8 (diff)
downloadserenity-41c0009f6d3db0f1a8baecbabc65c2464534dd31.zip
Kernel/Ext2FS: Don't hog inode lock in traverse_as_directory()
Reimplement directory traversal in terms of read_bytes() instead of doing direct block access. This lets us avoid taking the inode lock while iterating over the directory contents.
Diffstat (limited to 'Kernel/FileSystem/Ext2FileSystem.cpp')
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.cpp16
1 files changed, 6 insertions, 10 deletions
diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp
index 9127306fda..62a245c51b 100644
--- a/Kernel/FileSystem/Ext2FileSystem.cpp
+++ b/Kernel/FileSystem/Ext2FileSystem.cpp
@@ -1079,25 +1079,21 @@ Ext2FS::FeaturesReadOnly Ext2FS::get_features_readonly() const
KResult Ext2FSInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
{
- Locker locker(m_lock);
VERIFY(is_directory());
u8 buffer[max_block_size];
auto buf = UserOrKernelBuffer::for_kernel_buffer(buffer);
auto block_size = fs().block_size();
- bool allow_cache = true;
-
- if (m_block_list.is_empty())
- m_block_list = compute_block_list();
+ auto file_size = size();
// Directory entries are guaranteed not to span multiple blocks,
// so we can iterate over blocks separately.
- for (auto& block_index : m_block_list) {
- VERIFY(block_index.value() != 0);
- if (auto result = fs().read_block(block_index, &buf, block_size, 0, allow_cache); result.is_error()) {
- return result;
- }
+
+ for (u64 offset = 0; offset < file_size; offset += block_size) {
+ if (auto result = read_bytes(offset, block_size, buf, nullptr); result.is_error())
+ return result.error();
+
auto* entry = reinterpret_cast<ext2_dir_entry_2*>(buffer);
auto* entries_end = reinterpret_cast<ext2_dir_entry_2*>(buffer + block_size);
while (entry < entries_end) {