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