mirror of
https://github.com/RGBCube/serenity
synced 2025-05-15 12:54:58 +00:00
FS: Don't default to having a full InodeMetadata in every Inode.
This allows Ext2FS to keep its own ext2_inode around instead.
This commit is contained in:
parent
0cb074dc73
commit
d07b08a287
8 changed files with 93 additions and 80 deletions
|
@ -221,41 +221,33 @@ Ext2FSInode::~Ext2FSInode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FSInode::populate_metadata() const
|
InodeMetadata Ext2FSInode::metadata() const
|
||||||
{
|
{
|
||||||
m_metadata.inode = identifier();
|
InodeMetadata metadata;
|
||||||
m_metadata.size = m_raw_inode.i_size;
|
metadata.inode = identifier();
|
||||||
m_metadata.mode = m_raw_inode.i_mode;
|
metadata.size = m_raw_inode.i_size;
|
||||||
m_metadata.uid = m_raw_inode.i_uid;
|
metadata.mode = m_raw_inode.i_mode;
|
||||||
m_metadata.gid = m_raw_inode.i_gid;
|
metadata.uid = m_raw_inode.i_uid;
|
||||||
m_metadata.linkCount = m_raw_inode.i_links_count;
|
metadata.gid = m_raw_inode.i_gid;
|
||||||
m_metadata.atime = m_raw_inode.i_atime;
|
metadata.linkCount = m_raw_inode.i_links_count;
|
||||||
m_metadata.ctime = m_raw_inode.i_ctime;
|
metadata.atime = m_raw_inode.i_atime;
|
||||||
m_metadata.mtime = m_raw_inode.i_mtime;
|
metadata.ctime = m_raw_inode.i_ctime;
|
||||||
m_metadata.dtime = m_raw_inode.i_dtime;
|
metadata.mtime = m_raw_inode.i_mtime;
|
||||||
m_metadata.blockSize = fs().blockSize();
|
metadata.dtime = m_raw_inode.i_dtime;
|
||||||
m_metadata.blockCount = m_raw_inode.i_blocks;
|
metadata.blockSize = fs().blockSize();
|
||||||
|
metadata.blockCount = m_raw_inode.i_blocks;
|
||||||
|
|
||||||
if (isBlockDevice(m_raw_inode.i_mode) || isCharacterDevice(m_raw_inode.i_mode)) {
|
if (isBlockDevice(m_raw_inode.i_mode) || isCharacterDevice(m_raw_inode.i_mode)) {
|
||||||
unsigned dev = m_raw_inode.i_block[0];
|
unsigned dev = m_raw_inode.i_block[0];
|
||||||
m_metadata.majorDevice = (dev & 0xfff00) >> 8;
|
metadata.majorDevice = (dev & 0xfff00) >> 8;
|
||||||
m_metadata.minorDevice= (dev & 0xff) | ((dev >> 12) & 0xfff00);
|
metadata.minorDevice= (dev & 0xff) | ((dev >> 12) & 0xfff00);
|
||||||
}
|
}
|
||||||
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FSInode::flush_metadata()
|
void Ext2FSInode::flush_metadata()
|
||||||
{
|
{
|
||||||
dbgprintf("Ext2FSInode: flush_metadata for inode %u\n", index());
|
dbgprintf("Ext2FSInode: flush_metadata for inode %u\n", index());
|
||||||
m_raw_inode.i_size = m_metadata.size;
|
|
||||||
m_raw_inode.i_mode = m_metadata.mode;
|
|
||||||
m_raw_inode.i_uid = m_metadata.uid;
|
|
||||||
m_raw_inode.i_gid = m_metadata.gid;
|
|
||||||
m_raw_inode.i_links_count = m_metadata.linkCount;
|
|
||||||
m_raw_inode.i_atime = m_metadata.atime;
|
|
||||||
m_raw_inode.i_ctime = m_metadata.ctime;
|
|
||||||
m_raw_inode.i_mtime = m_metadata.mtime;
|
|
||||||
m_raw_inode.i_dtime = m_metadata.dtime;
|
|
||||||
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);
|
set_metadata_dirty(false);
|
||||||
}
|
}
|
||||||
|
@ -358,7 +350,7 @@ ssize_t Ext2FSInode::read_bytes(Unix::off_t offset, size_t count, byte* buffer,
|
||||||
bool Ext2FSInode::write(const ByteBuffer& data)
|
bool Ext2FSInode::write(const ByteBuffer& data)
|
||||||
{
|
{
|
||||||
// FIXME: Support writing to symlink inodes.
|
// FIXME: Support writing to symlink inodes.
|
||||||
ASSERT(!m_metadata.isSymbolicLink());
|
ASSERT(!is_symlink());
|
||||||
|
|
||||||
unsigned blocksNeededBefore = ceilDiv(size(), fs().blockSize());
|
unsigned blocksNeededBefore = ceilDiv(size(), fs().blockSize());
|
||||||
unsigned blocksNeededAfter = ceilDiv((unsigned)data.size(), fs().blockSize());
|
unsigned blocksNeededAfter = ceilDiv((unsigned)data.size(), fs().blockSize());
|
||||||
|
@ -595,7 +587,6 @@ bool Ext2FS::write_ext2_inode(unsigned inode, const ext2_inode& e2inode)
|
||||||
auto& cached_inode = *(*it).value;
|
auto& cached_inode = *(*it).value;
|
||||||
LOCKER(cached_inode.m_lock);
|
LOCKER(cached_inode.m_lock);
|
||||||
cached_inode.m_raw_inode = e2inode;
|
cached_inode.m_raw_inode = e2inode;
|
||||||
cached_inode.populate_metadata();
|
|
||||||
if (cached_inode.is_directory())
|
if (cached_inode.is_directory())
|
||||||
cached_inode.m_lookup_cache.clear();
|
cached_inode.m_lookup_cache.clear();
|
||||||
}
|
}
|
||||||
|
@ -924,6 +915,7 @@ InodeIdentifier Ext2FS::find_parent_of_inode(InodeIdentifier inode_id) const
|
||||||
Vector<RetainPtr<Ext2FSInode>> directories_in_group;
|
Vector<RetainPtr<Ext2FSInode>> directories_in_group;
|
||||||
|
|
||||||
for (unsigned i = 0; i < inodes_per_group(); ++i) {
|
for (unsigned i = 0; i < inodes_per_group(); ++i) {
|
||||||
|
// FIXME: Consult the inode bitmap to see which inodes to look into.
|
||||||
auto group_member = get_inode({ id(), firstInodeInGroup + i });
|
auto group_member = get_inode({ id(), firstInodeInGroup + i });
|
||||||
if (!group_member)
|
if (!group_member)
|
||||||
continue;
|
continue;
|
||||||
|
@ -990,3 +982,48 @@ void Ext2FSInode::one_retain_left()
|
||||||
{
|
{
|
||||||
// FIXME: I would like to not live forever, but uncached Ext2FS is fucking painful right now.
|
// FIXME: I would like to not live forever, but uncached Ext2FS is fucking painful right now.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Ext2FSInode::set_atime(Unix::time_t t)
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
m_raw_inode.i_atime = t;
|
||||||
|
set_metadata_dirty(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ext2FSInode::set_ctime(Unix::time_t t)
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
m_raw_inode.i_ctime = t;
|
||||||
|
set_metadata_dirty(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ext2FSInode::set_mtime(Unix::time_t t)
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
m_raw_inode.i_mtime = t;
|
||||||
|
set_metadata_dirty(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ext2FSInode::increment_link_count()
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
++m_raw_inode.i_links_count;
|
||||||
|
set_metadata_dirty(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ext2FSInode::decrement_link_count()
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
--m_raw_inode.i_links_count;
|
||||||
|
set_metadata_dirty(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -27,13 +27,18 @@ public:
|
||||||
private:
|
private:
|
||||||
// ^Inode
|
// ^Inode
|
||||||
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
||||||
virtual void populate_metadata() const override;
|
virtual InodeMetadata metadata() const override;
|
||||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
||||||
virtual InodeIdentifier lookup(const String& name) override;
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
virtual String reverse_lookup(InodeIdentifier) override;
|
virtual String reverse_lookup(InodeIdentifier) override;
|
||||||
virtual void flush_metadata() override;
|
virtual void flush_metadata() override;
|
||||||
virtual bool write(const ByteBuffer&) override;
|
virtual bool write(const ByteBuffer&) override;
|
||||||
virtual bool add_child(InodeIdentifier child_id, const String& name, byte file_type, int& error) override;
|
virtual bool add_child(InodeIdentifier child_id, const String& name, byte file_type, int& error) override;
|
||||||
|
virtual int set_atime(Unix::time_t) override;
|
||||||
|
virtual int set_ctime(Unix::time_t) override;
|
||||||
|
virtual int set_mtime(Unix::time_t) override;
|
||||||
|
virtual int increment_link_count() override;
|
||||||
|
virtual int decrement_link_count() override;
|
||||||
|
|
||||||
void populate_lookup_cache();
|
void populate_lookup_cache();
|
||||||
|
|
||||||
|
|
|
@ -111,56 +111,29 @@ void Inode::will_be_destroyed()
|
||||||
flush_metadata();
|
flush_metadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inode::set_atime(Unix::time_t ts)
|
int Inode::set_atime(Unix::time_t)
|
||||||
{
|
{
|
||||||
if (fs().is_readonly())
|
return -ENOTIMPL;
|
||||||
return -EROFS;
|
|
||||||
if (m_metadata.atime == ts)
|
|
||||||
return 0;
|
|
||||||
m_metadata.atime = ts;
|
|
||||||
m_metadata_dirty = true;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inode::set_ctime(Unix::time_t ts)
|
int Inode::set_ctime(Unix::time_t)
|
||||||
{
|
{
|
||||||
if (fs().is_readonly())
|
return -ENOTIMPL;
|
||||||
return -EROFS;
|
|
||||||
if (m_metadata.ctime == ts)
|
|
||||||
return 0;
|
|
||||||
m_metadata.ctime = ts;
|
|
||||||
m_metadata_dirty = true;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inode::set_mtime(Unix::time_t ts)
|
int Inode::set_mtime(Unix::time_t)
|
||||||
{
|
{
|
||||||
if (fs().is_readonly())
|
return -ENOTIMPL;
|
||||||
return -EROFS;
|
|
||||||
if (m_metadata.mtime == ts)
|
|
||||||
return 0;
|
|
||||||
m_metadata.mtime = ts;
|
|
||||||
m_metadata_dirty = true;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inode::increment_link_count()
|
int Inode::increment_link_count()
|
||||||
{
|
{
|
||||||
if (fs().is_readonly())
|
return -ENOTIMPL;
|
||||||
return -EROFS;
|
|
||||||
++m_metadata.linkCount;
|
|
||||||
m_metadata_dirty = true;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inode::decrement_link_count()
|
int Inode::decrement_link_count()
|
||||||
{
|
{
|
||||||
if (fs().is_readonly())
|
return -ENOTIMPL;
|
||||||
return -EROFS;
|
|
||||||
ASSERT(m_metadata.linkCount);
|
|
||||||
--m_metadata.linkCount;
|
|
||||||
m_metadata_dirty = true;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FS::sync()
|
void FS::sync()
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
bool is_directory() const { return metadata().isDirectory(); }
|
bool is_directory() const { return metadata().isDirectory(); }
|
||||||
|
|
||||||
InodeIdentifier identifier() const { return { fsid(), index() }; }
|
InodeIdentifier identifier() const { return { fsid(), index() }; }
|
||||||
const InodeMetadata& metadata() const { if (!m_metadata.isValid()) { populate_metadata(); } return m_metadata; }
|
virtual InodeMetadata metadata() const = 0;
|
||||||
|
|
||||||
ByteBuffer read_entire(FileDescriptor* = nullptr);
|
ByteBuffer read_entire(FileDescriptor* = nullptr);
|
||||||
|
|
||||||
|
@ -88,11 +88,11 @@ public:
|
||||||
|
|
||||||
bool is_metadata_dirty() const { return m_metadata_dirty; }
|
bool is_metadata_dirty() const { return m_metadata_dirty; }
|
||||||
|
|
||||||
int set_atime(Unix::time_t);
|
virtual int set_atime(Unix::time_t);
|
||||||
int set_ctime(Unix::time_t);
|
virtual int set_ctime(Unix::time_t);
|
||||||
int set_mtime(Unix::time_t);
|
virtual int set_mtime(Unix::time_t);
|
||||||
int increment_link_count();
|
virtual int increment_link_count();
|
||||||
int decrement_link_count();
|
virtual int decrement_link_count();
|
||||||
|
|
||||||
virtual void flush_metadata() = 0;
|
virtual void flush_metadata() = 0;
|
||||||
|
|
||||||
|
@ -101,10 +101,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
Inode(FS& fs, unsigned index);
|
Inode(FS& fs, unsigned index);
|
||||||
|
|
||||||
virtual void populate_metadata() const = 0;
|
|
||||||
void set_metadata_dirty(bool b) { m_metadata_dirty = b; }
|
void set_metadata_dirty(bool b) { m_metadata_dirty = b; }
|
||||||
|
|
||||||
mutable InodeMetadata m_metadata;
|
|
||||||
private:
|
private:
|
||||||
FS& m_fs;
|
FS& m_fs;
|
||||||
unsigned m_index { 0 };
|
unsigned m_index { 0 };
|
||||||
|
|
|
@ -184,9 +184,9 @@ SynthFSInode::~SynthFSInode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynthFSInode::populate_metadata() const
|
InodeMetadata SynthFSInode::metadata() const
|
||||||
{
|
{
|
||||||
// Already done when SynthFS created the file.
|
return m_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t SynthFSInode::read_bytes(Unix::off_t offset, size_t count, byte* buffer, FileDescriptor* descriptor)
|
ssize_t SynthFSInode::read_bytes(Unix::off_t offset, size_t count, byte* buffer, FileDescriptor* descriptor)
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
private:
|
private:
|
||||||
// ^Inode
|
// ^Inode
|
||||||
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
||||||
virtual void populate_metadata() const override;
|
virtual InodeMetadata metadata() const override;
|
||||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
||||||
virtual InodeIdentifier lookup(const String& name) override;
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
virtual String reverse_lookup(InodeIdentifier) override;
|
virtual String reverse_lookup(InodeIdentifier) override;
|
||||||
|
@ -64,4 +64,5 @@ private:
|
||||||
ByteBuffer m_data;
|
ByteBuffer m_data;
|
||||||
Function<ByteBuffer()> m_generator;
|
Function<ByteBuffer()> m_generator;
|
||||||
Vector<SynthFSInode*> m_children;
|
Vector<SynthFSInode*> m_children;
|
||||||
|
InodeMetadata m_metadata;
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,7 +51,7 @@ auto VFS::makeNode(InodeIdentifier inode) -> RetainPtr<Vnode>
|
||||||
if (!core_inode)
|
if (!core_inode)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto& metadata = core_inode->metadata();
|
auto metadata = core_inode->metadata();
|
||||||
|
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ auto VFS::makeNode(InodeIdentifier inode) -> RetainPtr<Vnode>
|
||||||
|
|
||||||
vnode->inode = inode;
|
vnode->inode = inode;
|
||||||
vnode->m_core_inode = move(core_inode);
|
vnode->m_core_inode = move(core_inode);
|
||||||
vnode->m_cachedMetadata = metadata;
|
|
||||||
|
|
||||||
#ifdef VFS_DEBUG
|
#ifdef VFS_DEBUG
|
||||||
kprintf("makeNode: inode=%u, size=%u, mode=%o, uid=%u, gid=%u\n", inode.index(), metadata.size, metadata.mode, metadata.uid, metadata.gid);
|
kprintf("makeNode: inode=%u, size=%u, mode=%o, uid=%u, gid=%u\n", inode.index(), metadata.size, metadata.mode, metadata.uid, metadata.gid);
|
||||||
|
@ -474,11 +473,12 @@ void Vnode::release()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const InodeMetadata& Vnode::metadata() const
|
InodeMetadata Vnode::metadata() const
|
||||||
{
|
{
|
||||||
if (m_core_inode)
|
if (m_core_inode)
|
||||||
return m_core_inode->metadata();
|
return m_core_inode->metadata();
|
||||||
return m_cachedMetadata;
|
ASSERT_NOT_REACHED();
|
||||||
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS::Mount::Mount(InodeIdentifier host, RetainPtr<FS>&& guest_fs)
|
VFS::Mount::Mount(InodeIdentifier host, RetainPtr<FS>&& guest_fs)
|
||||||
|
|
|
@ -38,7 +38,7 @@ class VFS;
|
||||||
class Vnode {
|
class Vnode {
|
||||||
public:
|
public:
|
||||||
InodeIdentifier inode;
|
InodeIdentifier inode;
|
||||||
const InodeMetadata& metadata() const;
|
InodeMetadata metadata() const;
|
||||||
|
|
||||||
bool inUse() const { return inode.is_valid() || m_characterDevice; }
|
bool inUse() const { return inode.is_valid() || m_characterDevice; }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue