mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 14:32:46 +00:00 
			
		
		
		
	Automatically call Inode::flush_metadata() before an Inode is destroyed.
Use a little template magic to have Retainable::release() call out to T::will_be_destroyed() if such a function exists before actually calling the destructor. This gives us full access to virtual functions in the pre-destruction code.
This commit is contained in:
		
							parent
							
								
									1f44cd9dd9
								
							
						
					
					
						commit
						d0f06e5f3f
					
				
					 6 changed files with 41 additions and 17 deletions
				
			
		|  | @ -1,39 +1,54 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include "Assertions.h" | ||||
| #include "StdLibExtras.h" | ||||
| 
 | ||||
| namespace AK { | ||||
| 
 | ||||
| template<class T> | ||||
| constexpr auto call_will_be_destroyed_if_present(T* object) -> decltype(object->will_be_destroyed(), TrueType { }) | ||||
| { | ||||
|     object->will_be_destroyed(); | ||||
|     return { }; | ||||
| } | ||||
| 
 | ||||
| constexpr auto call_will_be_destroyed_if_present(...) -> FalseType | ||||
| { | ||||
|     return { }; | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| class Retainable { | ||||
| public: | ||||
|     void retain() | ||||
|     { | ||||
|         ASSERT(m_retainCount); | ||||
|         ++m_retainCount; | ||||
|         ASSERT(m_retain_count); | ||||
|         ++m_retain_count; | ||||
|     } | ||||
| 
 | ||||
|     void release() | ||||
|     { | ||||
|         ASSERT(m_retainCount); | ||||
|         if (!--m_retainCount) | ||||
|         ASSERT(m_retain_count); | ||||
|         if (!--m_retain_count) { | ||||
|             call_will_be_destroyed_if_present(static_cast<T*>(this)); | ||||
|             delete static_cast<T*>(this); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     int retainCount() const | ||||
|     int retain_count() const | ||||
|     { | ||||
|         return m_retainCount; | ||||
|         return m_retain_count; | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     Retainable() { } | ||||
|     ~Retainable() | ||||
|     { | ||||
|         ASSERT(!m_retainCount); | ||||
|         ASSERT(!m_retain_count); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     int m_retainCount { 1 }; | ||||
|     int m_retain_count { 1 }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -83,7 +83,7 @@ ByteBuffer procfs$pid_vmo(Process& process) | |||
|             region->vmo().is_anonymous() ? "anonymous" : "file-backed", | ||||
|             region->vmo().name().characters(), | ||||
|             ®ion->vmo(), | ||||
|             region->vmo().retainCount()); | ||||
|             region->vmo().retain_count()); | ||||
|         for (size_t i = 0; i < region->vmo().page_count(); ++i) { | ||||
|             auto& physical_page = region->vmo().physical_pages()[i]; | ||||
|             ptr += ksprintf(ptr, "P%x%s(%u) ", | ||||
|  | @ -205,7 +205,7 @@ ByteBuffer procfs$mm() | |||
|         ptr += ksprintf(ptr, "VMO: %p %s(%u): p:%4u %s\n", | ||||
|             vmo, | ||||
|             vmo->is_anonymous() ? "anon" : "file", | ||||
|             vmo->retainCount(), | ||||
|             vmo->retain_count(), | ||||
|             vmo->page_count(), | ||||
|             vmo->name().characters()); | ||||
|     } | ||||
|  |  | |||
|  | @ -1104,7 +1104,7 @@ int Process::sys$utime(const char* pathname, const Unix::utimbuf* buf) | |||
|         atime = now; | ||||
|     } | ||||
|     inode.set_atime(atime); | ||||
|     inode.set_mtime(atime); | ||||
|     inode.set_mtime(mtime); | ||||
|     inode.flush_metadata(); | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -317,6 +317,7 @@ void Ext2FSInode::flush_metadata() | |||
|     m_raw_inode.i_dtime = m_metadata.dtime; | ||||
|     m_raw_inode.i_blocks = m_metadata.blockCount; | ||||
|     fs().write_ext2_inode(index(), m_raw_inode); | ||||
|     set_metadata_dirty(false); | ||||
| } | ||||
| 
 | ||||
| RetainPtr<Inode> Ext2FS::get_inode(InodeIdentifier inode) const | ||||
|  |  | |||
|  | @ -129,6 +129,12 @@ Inode::~Inode() | |||
| { | ||||
| } | ||||
| 
 | ||||
| void Inode::will_be_destroyed() | ||||
| { | ||||
|     if (m_metadata_dirty) | ||||
|         flush_metadata(); | ||||
| } | ||||
| 
 | ||||
| int Inode::set_atime(Unix::time_t ts) | ||||
| { | ||||
|     if (fs().is_readonly()) | ||||
|  | @ -136,7 +142,7 @@ int Inode::set_atime(Unix::time_t ts) | |||
|     if (m_metadata.atime == ts) | ||||
|         return 0; | ||||
|     m_metadata.atime = ts; | ||||
|     m_dirty = true; | ||||
|     m_metadata_dirty = true; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -147,7 +153,7 @@ int Inode::set_ctime(Unix::time_t ts) | |||
|     if (m_metadata.ctime == ts) | ||||
|         return 0; | ||||
|     m_metadata.ctime = ts; | ||||
|     m_dirty = true; | ||||
|     m_metadata_dirty = true; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -158,6 +164,6 @@ int Inode::set_mtime(Unix::time_t ts) | |||
|     if (m_metadata.mtime == ts) | ||||
|         return 0; | ||||
|     m_metadata.mtime = ts; | ||||
|     m_dirty = true; | ||||
|     m_metadata_dirty = true; | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -87,7 +87,7 @@ public: | |||
|     virtual InodeIdentifier lookup(const String& name) = 0; | ||||
|     virtual String reverse_lookup(InodeIdentifier) = 0; | ||||
| 
 | ||||
|     bool is_dirty() const { return m_dirty; } | ||||
|     bool is_metadata_dirty() const { return m_metadata_dirty; } | ||||
| 
 | ||||
|     int set_atime(Unix::time_t); | ||||
|     int set_ctime(Unix::time_t); | ||||
|  | @ -95,6 +95,8 @@ public: | |||
| 
 | ||||
|     virtual void flush_metadata() = 0; | ||||
| 
 | ||||
|     void will_be_destroyed(); | ||||
| 
 | ||||
| protected: | ||||
|     Inode(FS& fs, unsigned index) | ||||
|         : m_fs(fs) | ||||
|  | @ -103,13 +105,13 @@ protected: | |||
|     } | ||||
| 
 | ||||
|     virtual void populate_metadata() const = 0; | ||||
|     void set_dirty(bool b) { m_dirty = b; } | ||||
|     void set_metadata_dirty(bool b) { m_metadata_dirty = b; } | ||||
| 
 | ||||
|     mutable InodeMetadata m_metadata; | ||||
| private: | ||||
|     FS& m_fs; | ||||
|     unsigned m_index { 0 }; | ||||
|     bool m_dirty { false }; | ||||
|     bool m_metadata_dirty { false }; | ||||
| }; | ||||
| 
 | ||||
| inline FS* InodeIdentifier::fs() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling