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 | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "Assertions.h" | #include "Assertions.h" | ||||||
|  | #include "StdLibExtras.h" | ||||||
| 
 | 
 | ||||||
| namespace AK { | 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> | template<typename T> | ||||||
| class Retainable { | class Retainable { | ||||||
| public: | public: | ||||||
|     void retain() |     void retain() | ||||||
|     { |     { | ||||||
|         ASSERT(m_retainCount); |         ASSERT(m_retain_count); | ||||||
|         ++m_retainCount; |         ++m_retain_count; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void release() |     void release() | ||||||
|     { |     { | ||||||
|         ASSERT(m_retainCount); |         ASSERT(m_retain_count); | ||||||
|         if (!--m_retainCount) |         if (!--m_retain_count) { | ||||||
|  |             call_will_be_destroyed_if_present(static_cast<T*>(this)); | ||||||
|             delete static_cast<T*>(this); |             delete static_cast<T*>(this); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     int retainCount() const |     int retain_count() const | ||||||
|     { |     { | ||||||
|         return m_retainCount; |         return m_retain_count; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     Retainable() { } |     Retainable() { } | ||||||
|     ~Retainable() |     ~Retainable() | ||||||
|     { |     { | ||||||
|         ASSERT(!m_retainCount); |         ASSERT(!m_retain_count); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | 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().is_anonymous() ? "anonymous" : "file-backed", | ||||||
|             region->vmo().name().characters(), |             region->vmo().name().characters(), | ||||||
|             ®ion->vmo(), |             ®ion->vmo(), | ||||||
|             region->vmo().retainCount()); |             region->vmo().retain_count()); | ||||||
|         for (size_t i = 0; i < region->vmo().page_count(); ++i) { |         for (size_t i = 0; i < region->vmo().page_count(); ++i) { | ||||||
|             auto& physical_page = region->vmo().physical_pages()[i]; |             auto& physical_page = region->vmo().physical_pages()[i]; | ||||||
|             ptr += ksprintf(ptr, "P%x%s(%u) ", |             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", |         ptr += ksprintf(ptr, "VMO: %p %s(%u): p:%4u %s\n", | ||||||
|             vmo, |             vmo, | ||||||
|             vmo->is_anonymous() ? "anon" : "file", |             vmo->is_anonymous() ? "anon" : "file", | ||||||
|             vmo->retainCount(), |             vmo->retain_count(), | ||||||
|             vmo->page_count(), |             vmo->page_count(), | ||||||
|             vmo->name().characters()); |             vmo->name().characters()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1104,7 +1104,7 @@ int Process::sys$utime(const char* pathname, const Unix::utimbuf* buf) | ||||||
|         atime = now; |         atime = now; | ||||||
|     } |     } | ||||||
|     inode.set_atime(atime); |     inode.set_atime(atime); | ||||||
|     inode.set_mtime(atime); |     inode.set_mtime(mtime); | ||||||
|     inode.flush_metadata(); |     inode.flush_metadata(); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -317,6 +317,7 @@ void Ext2FSInode::flush_metadata() | ||||||
|     m_raw_inode.i_dtime = m_metadata.dtime; |     m_raw_inode.i_dtime = m_metadata.dtime; | ||||||
|     m_raw_inode.i_blocks = m_metadata.blockCount; |     m_raw_inode.i_blocks = m_metadata.blockCount; | ||||||
|     fs().write_ext2_inode(index(), m_raw_inode); |     fs().write_ext2_inode(index(), m_raw_inode); | ||||||
|  |     set_metadata_dirty(false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RetainPtr<Inode> Ext2FS::get_inode(InodeIdentifier inode) const | 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) | int Inode::set_atime(Unix::time_t ts) | ||||||
| { | { | ||||||
|     if (fs().is_readonly()) |     if (fs().is_readonly()) | ||||||
|  | @ -136,7 +142,7 @@ int Inode::set_atime(Unix::time_t ts) | ||||||
|     if (m_metadata.atime == ts) |     if (m_metadata.atime == ts) | ||||||
|         return 0; |         return 0; | ||||||
|     m_metadata.atime = ts; |     m_metadata.atime = ts; | ||||||
|     m_dirty = true; |     m_metadata_dirty = true; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -147,7 +153,7 @@ int Inode::set_ctime(Unix::time_t ts) | ||||||
|     if (m_metadata.ctime == ts) |     if (m_metadata.ctime == ts) | ||||||
|         return 0; |         return 0; | ||||||
|     m_metadata.ctime = ts; |     m_metadata.ctime = ts; | ||||||
|     m_dirty = true; |     m_metadata_dirty = true; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -158,6 +164,6 @@ int Inode::set_mtime(Unix::time_t ts) | ||||||
|     if (m_metadata.mtime == ts) |     if (m_metadata.mtime == ts) | ||||||
|         return 0; |         return 0; | ||||||
|     m_metadata.mtime = ts; |     m_metadata.mtime = ts; | ||||||
|     m_dirty = true; |     m_metadata_dirty = true; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ public: | ||||||
|     virtual InodeIdentifier lookup(const String& name) = 0; |     virtual InodeIdentifier lookup(const String& name) = 0; | ||||||
|     virtual String reverse_lookup(InodeIdentifier) = 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_atime(Unix::time_t); | ||||||
|     int set_ctime(Unix::time_t); |     int set_ctime(Unix::time_t); | ||||||
|  | @ -95,6 +95,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     virtual void flush_metadata() = 0; |     virtual void flush_metadata() = 0; | ||||||
| 
 | 
 | ||||||
|  |     void will_be_destroyed(); | ||||||
|  | 
 | ||||||
| protected: | protected: | ||||||
|     Inode(FS& fs, unsigned index) |     Inode(FS& fs, unsigned index) | ||||||
|         : m_fs(fs) |         : m_fs(fs) | ||||||
|  | @ -103,13 +105,13 @@ protected: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     virtual void populate_metadata() const = 0; |     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; |     mutable InodeMetadata m_metadata; | ||||||
| private: | private: | ||||||
|     FS& m_fs; |     FS& m_fs; | ||||||
|     unsigned m_index { 0 }; |     unsigned m_index { 0 }; | ||||||
|     bool m_dirty { false }; |     bool m_metadata_dirty { false }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline FS* InodeIdentifier::fs() | inline FS* InodeIdentifier::fs() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling