diff --git a/AK/Retainable.h b/AK/Retainable.h index 05757bea7e..b14ca56a24 100644 --- a/AK/Retainable.h +++ b/AK/Retainable.h @@ -17,6 +17,18 @@ constexpr auto call_will_be_destroyed_if_present(...) -> FalseType return { }; } +template +constexpr auto call_one_retain_left_if_present(T* object) -> decltype(object->one_retain_left(), TrueType { }) +{ + object->one_retain_left(); + return { }; +} + +constexpr auto call_one_retain_left_if_present(...) -> FalseType +{ + return { }; +} + template class Retainable { public: @@ -29,9 +41,12 @@ public: void release() { ASSERT(m_retain_count); - if (!--m_retain_count) { + --m_retain_count; + if (m_retain_count == 0) { call_will_be_destroyed_if_present(static_cast(this)); delete static_cast(this); + } else if (m_retain_count == 1) { + call_one_retain_left_if_present(static_cast(this)); } } diff --git a/VirtualFileSystem/Ext2FileSystem.cpp b/VirtualFileSystem/Ext2FileSystem.cpp index 74ed4fa359..af7e223ae4 100644 --- a/VirtualFileSystem/Ext2FileSystem.cpp +++ b/VirtualFileSystem/Ext2FileSystem.cpp @@ -985,3 +985,8 @@ String Ext2FSInode::reverse_lookup(InodeIdentifier child_id) } return { }; } + +void Ext2FSInode::one_retain_left() +{ + fs().m_inode_cache.remove(index()); +} diff --git a/VirtualFileSystem/Ext2FileSystem.h b/VirtualFileSystem/Ext2FileSystem.h index 44aefba1ca..9ab407267b 100644 --- a/VirtualFileSystem/Ext2FileSystem.h +++ b/VirtualFileSystem/Ext2FileSystem.h @@ -21,6 +21,9 @@ public: size_t size() const { return m_raw_inode.i_size; } bool is_symlink() const { return isSymbolicLink(m_raw_inode.i_mode); } + // ^Inode (Retainable magic) + virtual void one_retain_left() override; + private: // ^Inode virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override; diff --git a/VirtualFileSystem/FileSystem.h b/VirtualFileSystem/FileSystem.h index 5bd7635417..551c7b4b13 100644 --- a/VirtualFileSystem/FileSystem.h +++ b/VirtualFileSystem/FileSystem.h @@ -63,6 +63,8 @@ class Inode : public Retainable { public: virtual ~Inode(); + virtual void one_retain_left() { } + FS& fs() { return m_fs; } const FS& fs() const { return m_fs; } unsigned fsid() const;