1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 15:28:11 +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:
Andreas Kling 2018-12-19 22:28:09 +01:00
parent 1f44cd9dd9
commit d0f06e5f3f
6 changed files with 41 additions and 17 deletions

View file

@ -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 };
}; };
} }

View file

@ -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(),
&region->vmo(), &region->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());
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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;
} }

View file

@ -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()