diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp index 08c77aa3a0..1d66841459 100644 --- a/Kernel/FileSystem/Ext2FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FileSystem.cpp @@ -937,15 +937,12 @@ ErrorOr Ext2FSInode::resize(u64 new_size) ErrorOr Ext2FSInode::write_bytes(off_t offset, size_t count, UserOrKernelBuffer const& data, OpenFileDescription* description) { + VERIFY(m_inode_lock.is_locked()); VERIFY(offset >= 0); if (count == 0) return 0; - MutexLocker inode_locker(m_inode_lock); - - TRY(prepare_to_write_data()); - if (is_symlink()) { VERIFY(offset == 0); if (max((size_t)(offset + count), (size_t)m_raw_inode.i_size) < max_inline_symlink_length) { diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 69f495d101..62f37aa7a7 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -253,9 +253,7 @@ void Inode::did_delete_self() ErrorOr Inode::prepare_to_write_data() { - // FIXME: It's a poor design that filesystems are expected to call this before writing out data. - // We should funnel everything through an interface at the VirtualFileSystem layer so this can happen from a single place. - MutexLocker locker(m_inode_lock); + VERIFY(m_inode_lock.is_locked()); if (fs().is_readonly()) return EROFS; auto metadata = this->metadata(); diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index 479c86167c..3974d96350 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -31,6 +31,7 @@ class Inode : public ListedRefCounted , public Weakable { friend class VirtualFileSystem; friend class FileSystem; + friend class InodeFile; public: virtual ~Inode(); diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp index bbc030908e..04056e6e88 100644 --- a/Kernel/FileSystem/InodeFile.cpp +++ b/Kernel/FileSystem/InodeFile.cpp @@ -42,7 +42,12 @@ ErrorOr InodeFile::write(OpenFileDescription& description, u64 offset, U if (Checked::addition_would_overflow(offset, count)) return EOVERFLOW; - auto nwritten = TRY(m_inode->write_bytes(offset, count, data, &description)); + size_t nwritten = 0; + { + MutexLocker locker(m_inode->m_inode_lock); + TRY(m_inode->prepare_to_write_data()); + nwritten = TRY(m_inode->write_bytes(offset, count, data, &description)); + } if (nwritten > 0) { auto mtime_result = m_inode->set_mtime(kgettimeofday().to_truncated_seconds()); Thread::current()->did_file_write(nwritten); diff --git a/Kernel/FileSystem/TmpFS.cpp b/Kernel/FileSystem/TmpFS.cpp index 2c4ba99891..a0dbf463f3 100644 --- a/Kernel/FileSystem/TmpFS.cpp +++ b/Kernel/FileSystem/TmpFS.cpp @@ -108,12 +108,10 @@ ErrorOr TmpFSInode::read_bytes(off_t offset, size_t size, UserOrKernelBu ErrorOr TmpFSInode::write_bytes(off_t offset, size_t size, UserOrKernelBuffer const& buffer, OpenFileDescription*) { - MutexLocker locker(m_inode_lock); + VERIFY(m_inode_lock.is_locked()); VERIFY(!is_directory()); VERIFY(offset >= 0); - TRY(prepare_to_write_data()); - off_t old_size = m_metadata.size; off_t new_size = m_metadata.size; if (static_cast(offset + size) > new_size) diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index d17530e344..ac9eb700bc 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -693,6 +693,8 @@ ErrorOr VirtualFileSystem::symlink(StringView target, StringView linkpath, auto inode = TRY(parent_inode.create_child(basename, S_IFLNK | 0644, 0, current_process.euid(), current_process.egid())); auto target_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast((u8 const*)target.characters_without_null_termination())); + MutexLocker locker(inode->m_inode_lock); + TRY(inode->prepare_to_write_data()); TRY(inode->write_bytes(0, target.length(), target_buffer, nullptr)); return {}; }