From fff49ab6d32444aae6dfcad98f239572593c7dd4 Mon Sep 17 00:00:00 2001 From: Liav A Date: Fri, 23 Feb 2024 17:18:25 +0200 Subject: [PATCH] Kernel/FileSystem: Avoid double locking m_inode_lock in the Ext2 driver --- Kernel/FileSystem/Ext2FS/Inode.cpp | 5 +++-- Kernel/FileSystem/Inode.cpp | 6 ++++++ Kernel/FileSystem/Inode.h | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Kernel/FileSystem/Ext2FS/Inode.cpp b/Kernel/FileSystem/Ext2FS/Inode.cpp index 43faef822f..a2930d9127 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.cpp +++ b/Kernel/FileSystem/Ext2FS/Inode.cpp @@ -594,6 +594,7 @@ ErrorOr Ext2FSInode::read_bytes_locked(off_t offset, size_t count, UserO ErrorOr Ext2FSInode::resize(u64 new_size) { + VERIFY(m_inode_lock.is_locked()); auto old_size = size(); if (old_size == new_size) return {}; @@ -655,7 +656,7 @@ ErrorOr Ext2FSInode::resize(u64 new_size) auto clear_from = old_size; u8 zero_buffer[PAGE_SIZE] {}; while (bytes_to_clear) { - auto nwritten = TRY(write_bytes(clear_from, min(static_cast(sizeof(zero_buffer)), bytes_to_clear), UserOrKernelBuffer::for_kernel_buffer(zero_buffer), nullptr)); + auto nwritten = TRY(prepare_and_write_bytes_locked(clear_from, min(static_cast(sizeof(zero_buffer)), bytes_to_clear), UserOrKernelBuffer::for_kernel_buffer(zero_buffer), nullptr)); VERIFY(nwritten != 0); bytes_to_clear -= nwritten; clear_from += nwritten; @@ -816,7 +817,7 @@ ErrorOr Ext2FSInode::write_directory(Vector& entries TRY(resize(serialized_bytes_count)); auto buffer = UserOrKernelBuffer::for_kernel_buffer(directory_data.data()); - auto nwritten = TRY(write_bytes(0, serialized_bytes_count, buffer, nullptr)); + auto nwritten = TRY(prepare_and_write_bytes_locked(0, serialized_bytes_count, buffer, nullptr)); set_metadata_dirty(true); if (nwritten != directory_data.size()) return EIO; diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 9e9763fa2d..8325014131 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -97,6 +97,12 @@ ErrorOr Inode::truncate(u64 size) ErrorOr Inode::write_bytes(off_t offset, size_t length, UserOrKernelBuffer const& target_buffer, OpenFileDescription* open_description) { MutexLocker locker(m_inode_lock); + return prepare_and_write_bytes_locked(offset, length, target_buffer, open_description); +} + +ErrorOr Inode::prepare_and_write_bytes_locked(off_t offset, size_t length, UserOrKernelBuffer const& target_buffer, OpenFileDescription* open_description) +{ + VERIFY(m_inode_lock.is_locked()); TRY(prepare_to_write_data()); return write_bytes_locked(offset, length, target_buffer, open_description); } diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index 75d795f8f8..dfd1aa17ee 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -121,6 +121,8 @@ protected: mutable Mutex m_inode_lock { "Inode"sv }; + ErrorOr prepare_and_write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*); + virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) = 0; virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const = 0; virtual ErrorOr truncate_locked(u64) { return {}; }