Kernel/FileSystem: Enforce locking of m_inode_lock when truncating Inode

Such operation is almost equivalent to writing on an Inode, so lock the
Inode m_inode_lock exclusively.
All FileSystem Inode implementations then override a new method called
truncate_locked which should implement the actual truncating.
This commit is contained in:
Liav A 2024-02-10 12:49:31 +02:00 committed by Andrew Kaster
parent 53dd04e219
commit b63a1dda63
13 changed files with 23 additions and 14 deletions

View file

@ -1071,9 +1071,9 @@ ErrorOr<void> Ext2FSInode::chown(UserID uid, GroupID gid)
return {};
}
ErrorOr<void> Ext2FSInode::truncate(u64 size)
ErrorOr<void> Ext2FSInode::truncate_locked(u64 size)
{
MutexLocker locker(m_inode_lock);
VERIFY(m_inode_lock.is_locked());
if (static_cast<u64>(m_raw_inode.i_size) == size)
return {};
TRY(resize(size));

View file

@ -42,7 +42,7 @@ private:
virtual ErrorOr<void> decrement_link_count() override;
virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> truncate_locked(u64) override;
virtual ErrorOr<int> get_block_address(int) override;
ErrorOr<void> write_directory(Vector<Ext2FSDirectoryEntry>&);

View file

@ -140,7 +140,7 @@ ErrorOr<void> ISO9660Inode::chown(UserID, GroupID)
return EROFS;
}
ErrorOr<void> ISO9660Inode::truncate(u64)
ErrorOr<void> ISO9660Inode::truncate_locked(u64)
{
return EROFS;
}

View file

@ -31,7 +31,7 @@ public:
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> truncate_locked(u64) override;
virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
private:

View file

@ -88,6 +88,12 @@ void Inode::will_be_destroyed()
(void)flush_metadata();
}
ErrorOr<void> Inode::truncate(u64 size)
{
MutexLocker locker(m_inode_lock);
return truncate_locked(size);
}
ErrorOr<size_t> Inode::write_bytes(off_t offset, size_t length, UserOrKernelBuffer const& target_buffer, OpenFileDescription* open_description)
{
MutexLocker locker(m_inode_lock);

View file

@ -56,6 +56,7 @@ public:
ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*);
ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const;
ErrorOr<size_t> read_until_filled_or_end(off_t, size_t, UserOrKernelBuffer buffer, OpenFileDescription*) const;
ErrorOr<void> truncate(u64);
virtual ErrorOr<void> attach(OpenFileDescription&) { return {}; }
virtual void detach(OpenFileDescription&) { }
@ -70,7 +71,6 @@ public:
virtual ErrorOr<void> replace_child(StringView name, Inode&) = 0;
virtual ErrorOr<void> chmod(mode_t) = 0;
virtual ErrorOr<void> chown(UserID, GroupID) = 0;
virtual ErrorOr<void> truncate(u64) { return {}; }
ErrorOr<NonnullRefPtr<Custody>> resolve_as_link(Credentials const&, Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const;
@ -123,6 +123,7 @@ protected:
virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) = 0;
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const = 0;
virtual ErrorOr<void> truncate_locked(u64) { return {}; }
private:
ErrorOr<bool> try_apply_flock(Process const&, OpenFileDescription const&, flock const&);

View file

@ -284,8 +284,9 @@ ErrorOr<void> Plan9FSInode::chown(UserID, GroupID)
return ENOTIMPL;
}
ErrorOr<void> Plan9FSInode::truncate(u64 new_size)
ErrorOr<void> Plan9FSInode::truncate_locked(u64 new_size)
{
VERIFY(m_inode_lock.is_locked());
if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L) {
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tsetattr };
SetAttrMask valid = SetAttrMask::Size;

View file

@ -33,7 +33,7 @@ public:
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> truncate_locked(u64) override;
private:
// ^Inode

View file

@ -50,7 +50,7 @@ private:
virtual ErrorOr<void> chmod(mode_t) override { return EROFS; }
virtual ErrorOr<void> chown(UserID, GroupID) override { return EROFS; }
virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) override { return EROFS; }
virtual ErrorOr<void> truncate(u64) override { return EROFS; }
virtual ErrorOr<void> truncate_locked(u64) override { return EROFS; }
// ^Inode (Silent ignore handling)
virtual ErrorOr<void> flush_metadata() override { return {}; }

View file

@ -361,9 +361,9 @@ ErrorOr<void> RAMFSInode::remove_child(StringView name)
return {};
}
ErrorOr<void> RAMFSInode::truncate(u64 size)
ErrorOr<void> RAMFSInode::truncate_locked(u64 size)
{
MutexLocker locker(m_inode_lock);
VERIFY(m_inode_lock.is_locked());
VERIFY(!is_directory());
u64 block_index = size / DataBlock::block_size + ((size % DataBlock::block_size == 0) ? 0 : 1);

View file

@ -34,7 +34,7 @@ public:
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> truncate_locked(u64) override;
virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
private:

View file

@ -105,8 +105,9 @@ ErrorOr<void> SysFSInode::chown(UserID, GroupID)
return EPERM;
}
ErrorOr<void> SysFSInode::truncate(u64 size)
ErrorOr<void> SysFSInode::truncate_locked(u64 size)
{
VERIFY(m_inode_lock.is_locked());
return m_associated_component->truncate(size);
}

View file

@ -34,7 +34,7 @@ protected:
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> truncate_locked(u64) override;
virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
virtual ErrorOr<void> attach(OpenFileDescription& description) override final;