summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2022-08-06 18:24:21 +0300
committerIdan Horowitz <idan.horowitz@gmail.com>2022-09-16 14:55:45 +0300
commit4f4717e3518e274012c77bd2143df00604e56db4 (patch)
treeaca6659bcc26353abfb4f8dcffa6c5c9b6ced3a1 /Kernel
parent843bd43c5be5b5d1b8bff8aa2a81b99ed232bc57 (diff)
downloadserenity-4f4717e3518e274012c77bd2143df00604e56db4.zip
Kernel/FileSystem: Mark ext2 inode block list non-const
The block list required a bit of work, and now the only method being declared const to bypass its const-iness is the read_bytes method that calls a new method called compute_block_list_with_exclusive_locking that takes care of proper locking before trying to update the block list data of the ext2 inode.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.cpp21
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.h6
2 files changed, 24 insertions, 3 deletions
diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp
index 48aa3b4cdd..1a09ee2309 100644
--- a/Kernel/FileSystem/Ext2FileSystem.cpp
+++ b/Kernel/FileSystem/Ext2FileSystem.cpp
@@ -798,6 +798,19 @@ ErrorOr<NonnullLockRefPtr<Inode>> Ext2FS::get_inode(InodeIdentifier inode) const
return new_inode;
}
+ErrorOr<void> Ext2FSInode::compute_block_list_with_exclusive_locking()
+{
+ // Note: We verify that the inode mutex is being held locked. Because only the read_bytes_locked()
+ // method uses this method and the mutex can be locked in shared mode when reading the Inode if
+ // it is an ext2 regular file, but also in exclusive mode, when the Inode is an ext2 directory and being
+ // traversed, we use another exclusive lock to ensure we always mutate the block list safely.
+ VERIFY(m_inode_lock.is_locked());
+ MutexLocker block_list_locker(m_block_list_lock);
+ if (m_block_list.is_empty())
+ m_block_list = TRY(compute_block_list());
+ return {};
+}
+
ErrorOr<size_t> Ext2FSInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* description) const
{
MutexLocker inode_locker(m_inode_lock);
@@ -817,8 +830,12 @@ ErrorOr<size_t> Ext2FSInode::read_bytes(off_t offset, size_t count, UserOrKernel
return nread;
}
- if (m_block_list.is_empty())
- m_block_list = TRY(compute_block_list());
+ // Note: We bypass the const declaration of this method, but this is a strong
+ // requirement to be able to accomplish the read operation successfully.
+ // We call this special method becuase it locks a separate mutex to ensure we
+ // update the block list of the inode safely, as the m_inode_lock is locked in
+ // shared mode.
+ TRY(const_cast<Ext2FSInode&>(*this).compute_block_list_with_exclusive_locking());
if (m_block_list.is_empty()) {
dmesgln("Ext2FSInode[{}]::read_bytes(): Empty block list", identifier());
diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h
index 8441fc70a3..8a5abff095 100644
--- a/Kernel/FileSystem/Ext2FileSystem.h
+++ b/Kernel/FileSystem/Ext2FileSystem.h
@@ -61,6 +61,8 @@ private:
ErrorOr<void> grow_triply_indirect_block(BlockBasedFileSystem::BlockIndex, size_t, Span<BlockBasedFileSystem::BlockIndex>, Vector<BlockBasedFileSystem::BlockIndex>&, unsigned&);
ErrorOr<void> shrink_triply_indirect_block(BlockBasedFileSystem::BlockIndex, size_t, size_t, unsigned&);
ErrorOr<void> flush_block_list();
+
+ ErrorOr<void> compute_block_list_with_exclusive_locking();
ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list() const;
ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list_with_meta_blocks() const;
ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list_impl(bool include_block_list_blocks) const;
@@ -70,9 +72,11 @@ private:
Ext2FS const& fs() const;
Ext2FSInode(Ext2FS&, InodeIndex);
- mutable Vector<BlockBasedFileSystem::BlockIndex> m_block_list;
+ Vector<BlockBasedFileSystem::BlockIndex> m_block_list;
HashMap<NonnullOwnPtr<KString>, InodeIndex> m_lookup_cache;
ext2_inode m_raw_inode {};
+
+ Mutex m_block_list_lock { "BlockList"sv };
};
class Ext2FS final : public BlockBasedFileSystem {